Mongoose $push keeps adding two entries

mongoose push to array
mongoose findoneandupdate promise
findoneandupdate push to array

Here are my user and product schemas:

const productSchema = new Schema({
  //... 
  addedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "users"
  }
});

const userSchema = new Schema({   
  //...
  addedItems: [{
    type: mongoose.Schema.ObjectId,
    ref: "products"
  }]
});

mongoose.model("products", productSchema);
mongoose.model("users", userSchema);

In my Node back end route I do this query:

User.findOneAndUpdate(
  { _id: req.body.id },
  { $push: { addedItems: newProduct._id } },
  { upsert: true, new: true },
  function(err, doc) {
    console.log(err, doc);
  }
);

The console.log prints out this:

{
    //...
    addedItems: [ 5ab0223118599214f4dd7803 ]
}

Everything looks good. I go to actually look at the data using the front-end website for my mongo db; I'm using mlab.com, and this is what shows:

{
//...
"addedItems": [
        {
            "$oid": "5ab0223118599214f4dd7803"
        },
        {
            "$oid": "5ab0223118599214f4dd7803"
        }
    ]
}

Question: What the heck happened? Why does it add an additional entry into addedItems ?! Even though my console.log only showed one.

Note:

I tested to see if the backend route was being called more than once. It is not.

It seems to be a problem with $push because if I just have { addedItems: newProduct._id } then only one entry goes in, but it overwrites the entire array.

Edit:

Made a test project to produce the same results: https://github.com/philliprognerud/test-mcve-stackoverflow

Can anyone figure out what's going on?


The problem is caused by your mixed used of promises (via async/await) and callbacks with the findOneAndUpdate call which ends up executing the command twice.

To fix the problem:

const updatedUser = await User.findOneAndUpdate(
  { id: userID },
  { $push: { addedItems: newProduct.id } },
  { upsert: true, new: true }
);

console.log(updatedUser);

Future readers note that the use of await isn't shown here in the question, but is in the MCVE.

$push, the $each modifier to add multiple documents to the the $slice modifier to keep only the first three sorted  The problem is caused by your mixed used of promises (via async/await) and callbacks with the findOneAndUpdate call which ends up executing the command twice.. To fix the problem:


I am facing similar issue. Just landed to this page. I find that previous answer is not very descriptive. So posting this:

export const updateUserHandler = async (req, res) => {
    const request = req.body;    
 await  User.findOneAndUpdate(                  //<== remove await 
  { _id: request.id },
  { $push: { addedItems: newProduct._id } },
  { upsert: true, new: true },
  (findErr, findRes) => {
        if (findErr) {
          res.status(500).send({
            message: 'Failed: to update user',
            IsSuccess: false,
            result: findErr
          });
        } else {
          res.status(200).send({
            message: 'Success:  to update user',
            IsSuccess: true,
            result: findRes
          });

        }
      }
);
  }

Here there are two async calls one is the async and other is await. Because of this there are two entries in the document. Just remove await from await User.findOneAndUpdate. It will work perfectly. Thanks!!

mongoose push, An easy to follow tutorial about how to use the mongoose push But to add or remove values from an array in mongoose, we have Each document has two fields – name and clubs (and _id field of Keep in the know! The processing of the push operation with modifiers occur in the following order, regardless of the order in which the modifiers appear:. Update array to add elements in the correct position.


This code $push keeps adding two entries: const ali={ "_id": "5eaa39a18e7719140e3f4430" };

//   return await customerModel.findOneAndUpdate(
//     ali,
//     {
//       "$push": {
//         "address": [objAdr],
//       },
//     },
//     function (error: any, success: any) {
//       if (error) {
//         console.log(error);
//       } else {
//         console.log(success);
//       }
//     }
//   );

My solutions working true:

return await customerModel
.findOneAndUpdate(
  { _id: ids },
  { $push: { "address": objAdr } }
)
.catch((err: string | undefined) => new Error(err));

How to Add Elements into an Array in MongoDB, Pushing, or adding, elements to an array is very useful for quickly appending a list by adding or moving items in an already existing Mongo DB document. The tutorial will explain using both negative and positive integers for the push operations, with there being more push options using Keep in the know! when validating an array of ID values (GitHub issue #12). Bumped version for release


When you await Query you are using the promise-like, specifically, .then() and .catch(() of Query. Passing a callback as well will result in the behavior you're describing.

If you await Query and .then() of Query simultaneously, would make the query execute twice

use:

await Model.findOneAndUpdate(query, doc, options)

OR

Model.findOneAndUpdate(query, doc, options, callback)

Use $push to insert elements into an array, Given this position value, MongoDB pushes the new element 'i' to the 8th Let's add them in the position before the last two elements. To keep the array to only the 3 most recent items, you then slice the recent-items. In this article, we've learned a bit about databases and ORMs on Node/Express, and a lot about how Mongoose schema and models are defined. We then used this information to design and implement Book, BookInstance, Author and Genre models for the LocalLibrary website.


Dynamically adding fields in the schema doesn't permit to add fields , Hi, When I dynamically add a field to a schema and instantiate it to a model, mongoose is made on this new field when I call save. var schema = new mongoose. Two solutions: Disable the strict option, (enabled by default), ensures that values added to our I wanted to keep the strict option to avoid unwanted fields. Insert document to MongoDB - To insert single document to MongoDB, call save() method on document instance. Callback function(err, document) is an optional argument to save() method. Insertion happens asynchronously and operations dependent on the inserted document has to be taken care. Find Example script.


Mongoose v5.9.20: SubDocuments, Mongoose has two distinct notions of subdocuments: arrays of subdocuments and single Subdocuments versus Nested Paths; Finding a Subdocument; Adding MongooseArray methods such as push, unshift, addToSet, and others cast If you create a schema with an array of objects, Mongoose will automatically  But simply adding entries in these tables via rfc prog. is not working, because new change documents are not displayed in material master in SAP system. So it seems that there is something which needs to be added because we need the changes to be displayed via such SAp functions. Another question is the numbering of change documents.


Express Tutorial Part 3: Using a Database (with Mongoose), There are two common approaches for interacting with a database: We have also decided to have a model for the genre so that values can be You can perform JavaScript array operations on these models (push, pop, unshift, etc.). Here we just specify one matching field (sport) but you can add more  However, it is prudent to keep the standard entry and, instead, add a separate entry that you customize. To add a boot entry, copy an existing boot entry, and then modify the copy. This topic applies to Windows Vista and later, Windows Server 2008 and later, and Windows Recovery Environment. Adding a new boot entry