简体   繁体   中英

Mongoose/Mongodb findOneAndUpdate while keeping what is already there

I'm saving many items per User in my db via mongoose, items end inside item (array) in the User schema. How do I tell mongodb to findOneAndUpdate while keeping the items that are already there ? Because right now the update basically override the whole item array in the db for that User.

What I have is this:

            var filter = { 'id': thisId };
            let update = { 
              'item': itemsArray,
              'updatedAt': Date.now()
            };

            User.findOneAndUpdate(filter, update, {upsert: true, new: true}, function(err, doc) {
                if (err) return res.send(500, {error: err});
                return;
            });

I've read about the $addToSet in the mongodb docs, but is it what I need here? How can I apply it to my query?

UPDATE : the $set as suggested below doesn't work. My example: I fetch 400 items inside the field 'item' , then with a conditional based on last update date, I fetch 50 items the second time, now let's say among these 50 there's one item which is not already present among the 400 previously added, I'm expecting it to add the item to the 400 becoming 401. Instead what happens is i now find 50 items total inside the 'item' field

SOLUTION I FOUND :

User.findOneAndUpdate(filter, { $set : {'updatedAt': Date.now()}, $addToSet : {'item': itemsArray} }, {upsert: true}, function(err, doc) {
                    if (err) return res.send(500, {error: err});
                    return;
                });

you should use $push:

var filter = { 'id': thisId };

User.findOneAndUpdate(filter, { 
   $set : { 'updatedAt': Date.now() }, 
   $push : { 'item': itemsArray } 
}, {upsert: true, new: true}, function(err, doc) {
   if (err) return res.send(500, {error: err});
   return;
});

Use $addToSet with $each to update the array and use $set to update the rest of the fields. This can be done in the same query.

In this case it will perform the upsert operation since document with name raj in not present.


user = { _id: ObjectID("5ff171ce57fd21194c9f0d71"),
  name: 'ankit',
  item: [ 'apple', 'orange' ] }

db.user.findOneAndUpdate({name:'raj'},{$set:{age:13},$addToSet:{item:{$each:['apple','banana']}}},{upsert:true,new:true})

Here it will simply update the fields including the array field.


user = { _id: ObjectID("5ff171ce57fd21194c9f0d71"),
  name: 'ankit',
  item: [ 'apple', 'orange' ] }

db.user.findOneAndUpdate({name:'ankit'},{$set:{age:1},$addToSet:{item:{$each:['apple','banana']}}},{upsert:true,new:true})

I think it's not best using the findOneAndUpdate() try this:

const filter = { 'id': thisId };
const user = await User.findOne(filter);
user.items.push(...itemsArray) // If itemsArray is an array
await user.save();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM