mongoose - How to manipulate/remove the sub-documents in MongoDB through MongooseJS? -
i have following schemas:
//define suberschema var suberschema = new schema({ _id: { type: schema.types.objectid, required: true }, constraints: [constraintschema] }); //define spaceinfoschema var spaceinfoschema = new schema({ spacename: string, subers: [suberschema], _id: { type: schema.types.objectid, required: true } });
i want manipulate/get subdocs when use following code, operates parentdocs.
- this returns array subers. should suber specified id?
spaceinfomodel.find({"_id": spaceid,"subers._id": userid}, "subers", callback);
- this removes whole document. should remove suber specified id?
spaceinfomodel.remove({"_id": spaceid,"subers._id": userid}, callback);
thanks in advance.
find()
return documents collection called on. in example spaceinfomodel
. query: spaceinfomodel.find({"_id": spaceid,"subers._id": userid}, "subers", callback);
checking document in spaceinfomodel
's collection matches id of spaceid
, has sub-doc id of userid
. if matching documents found returned array callback function.
at point can use helper function id()
retrieve sub-doc:
// using findone match findbyid spaceinfomodel.findone({"_id": spaceid,"subers._id": userid}, 'subers').exec().then(function(spaceinfo) { // spaceinfo.subers entire sub-doc array return spaceinfo.subers.id(userid); }).then(function(suber) { // suber }).then(null, function(err) { ... });
this has unfortunate side effect of returning sub-docs can prune down one. more efficient way have mongo pare down sub-doc array before returning parent doc. $elemmatch
projection operator can used this.
spaceinfomodel.findbyid(spaceid).select({subers: {$elemmatch: {_id: userid}}}).exec().then(function(spaceinfo) { // spaceinfo.subers array of matching sub-doc return spaceinfo.subers.id(userid); }).then(function(suber) { // suber }).then(null, function(err) { ... });
going beyond explore using aggregate pipeline unwind document sub-docs don't believe there gain on using elemmatch()
.
to remove sub-doc can done in similar manner. first approach requires retrieving entire array down , modifying locally pull()
before saving monogodb.
spaceinfomodel.findone({"_id": spaceid,"subers._id": userid}, 'subers').exec().then(function(spaceinfo) { // spaceinfo.subers entire sub-doc array // remove matching id spaceinfo.subers.pull({_id: userid}); // commit mongodb return spaceinfo.save(); }).then(function() { ... }).then(null, function(err) { ... });
again, done more efficiently directly on mongodb server.
spaceinfomodel.findbyidandupdate(spaceid, {$pull: {subers: {_id: userid}}}).select({subers: {$elemmatch: {_id: userid}}}).exec().then(function(spaceinfo) { // spaceinfo.subers array of matching sub-doc // original doc returned removed sub-doc on success return spaceinfo.subers.id(userid); }).then(function(suber) { // suber }).then(null, function(err) { ... });
note: $elemmatch
used return sub-doc removed. if don't care simplify to:
spaceinfomodel.findbyidandupdate(spaceid, {$pull: {subers: {_id: userid}}}).exec().then(function(spaceinfo) { ... }).then(null, function(err) { ... });
Comments
Post a Comment