How to update embedded document in mongoose?

2019-01-23 07:35发布

问题:

I've looked through the mongoose API, and many questions on SO and on the google group, and still can't figure out updating embedded documents.

I'm trying to update this particular userListings object with the contents of args.

for (var i = 0; i < req.user.userListings.length; i++) {
    if (req.user.userListings[i].listingId == req.params.listingId) {
        User.update({
            _id: req.user._id,
            'userListings._id': req.user.userListings[i]._id
        }, {
            'userListings.isRead': args.isRead,
            'userListings.isFavorite': args.isFavorite,
            'userListings.isArchived': args.isArchived
        }, function(err, user) {
            res.send(user);
        });
    }
}

Here are the schemas:

var userListingSchema = new mongoose.Schema({
    listingId: ObjectId,
    isRead: {
        type: Boolean,
        default: true
    },
    isFavorite: {
        type: Boolean,
        default: false
    },
    isArchived: {
        type: Boolean,
        default: false
    }
});

var userSchema = new mongoose.Schema({
    userListings: [userListingSchema]
});

This find also doesn't work, which is probably the first issue:

User.find({
    '_id': req.user._id,
    'userListings._id': req.user.userListings[i]._id
}, function(err, user) {
    console.log(err ? err : user);
});

which returns:

{ stack: [Getter/Setter],
  arguments: [ 'path', undefined ],
  type: 'non_object_property_call',
  message: [Getter/Setter] }

That should be the equivalent of this mongo client call:

db.users.find({'userListings._id': ObjectId("4e44850101fde3a3f3000002"), _id: ObjectId("4e4483912bb87f8ef2000212")})

Running:

mongoose v1.8.1
mongoose-auth v0.0.11
node v0.4.10 

回答1:

when you already have the user, you can just do something like this:

var listing = req.user.userListings.id(req.params.listingId);

listing.isRead = args.isRead;
listing.isFavorite = args.isFavorite;
listing.isArchived = args.isArchived;

req.user.save(function (err) {
  // ...
});

as found here: http://mongoosejs.com/docs/subdocs.html

Finding a sub-document

Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.

var doc = parent.children.id(id);

* * warning * *

as @zach pointed out, you have to declare the sub-document's schema before the actual document 's schema to be able to use the id() method.



回答2:

Is this just a mismatch on variables names?

You have user.userListings[i].listingId in the for loop but user.userListings[i]._id in the find.

Are you looking for listingId or _id?



回答3:

You have to save the parent object, and markModified the nested document.

That´s the way we do it

exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  Profile.findById(req.params.id, function (err, profile) {
    if (err) { return handleError(res, err); }
    if(!profile) { return res.send(404); }
    var updated = _.merge(profile, req.body);
    updated.markModified('NestedObj');
    updated.save(function (err) {
      if (err) { return handleError(res, err); }
      return res.json(200, profile);
    });
  });
};