Cedric Bongaerts Cedric Bongaerts - 1 year ago 192
Node.js Question

Mongodb | mongoose: Remove from nested document with $pull

I have the following two models:


var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var captureSchema = Schema({
type: String,
birdname: {type: String, required: true},
place: String,
note: String,
userId: String,
author: String,
picture: Schema.Types.Mixed,
created_at: Date,
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}],

module.exports = mongoose.model('Capture', captureSchema);


var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var commentSchema = Schema({
body: String,
userId: String,
author: String,
created_at: Date,
capture: [{ type: Schema.Types.ObjectId, ref: 'Capture'}]

module.exports = mongoose.model('Comment', commentSchema);

My goal is to remove a comment from a capture but I can't seem to figure out how to remove the ref 'id' from capture once I have deleted a comment.

Currently I'm using the following the remove a comment:

var Comment = require('../models/comment');
var Capture = require('../models/capture');


router.delete('/comments/:id', function(req, res){
Comment.remove({_id: req.params.id}, function(err){
res.json({result: err ? 'error' : 'ok'});
console.log('comment removed');

//DOES NOT WORK ---> Need assistance with $pull
Capture.update({_id: Capture.comments._id}, {
$pull : {'comments' : req.params.id}}, function(err, data) {
if(err) throw err;

But for some reason, only my comment gets deleted, but the reference stays on my capture as followed (example):

"_id": "574b640e39c34ad806b7eab6",
"created_at": "2016-05-29T21:50:06.772Z",
"picture": "https://cdn.filepicker.io/api/file/C9Z73CQwCiFP8pdB5W7A",
"author": "Cedric Bongaerts",
"userId": "facebook|10153403872376529",
"place": "Afrika",
"birdname": "Mountain Serpent Eagle",
"type": "ok",
"__v": 14,
"comments": [

While my comments are empty (been deleted).

An extra thing to mention:
When I get the capture by 'id'
, it does show that the comment is deleted.. It only stays when viewing the full captures list

Answer Source

You need to get the comment document you're removing so that you can access its capture field that contains the _id of the Capture document to remove the comment reference from. The easiest way to do that is to use findByIdAndRemove instead of just remove when removing the comment:

Comment.findByIdAndRemove(req.params.id, function(err, comment){
    if (comment) {
        Capture.update({_id: comment.capture}, {
                $pull : {comments: req.params.id}
            }, function(err, data) { ... });

Note that this assumes that capture is not an array (as discussed in the comments), and is defined like this instead:

capture: { type: Schema.Types.ObjectId, ref: 'Capture'}