简体   繁体   中英

MongoDb: Insert or update multiple documents with a unique index

I have a MongoDB collection with a unique index. I am trying to insert or update an array of documents into that collection.

If there is NO existing document in the collection matching the unique index of the document, that new document should be inserted into the collection.

However, if there IS already a document in the collection with that unique index, it should be updated with the fields of the new document. Any fields that are NOT present in the new document should be left untouched.

This is what I have currently which is working for inserting (but NOT for updating).

const mongojs = require('mongojs');
const db = mongojs('mongodb://username:password@address.mlab.com:37230/database');

             // items is an array of documents
db.items.insert(items, (err, task) => {
    if (err) {
      console.log(err);
    }
  })

I understand this is wrong and it currently gives this error:

E11000 duplicate key error index: database.items.$upc_1 dup key:

What is the proper query for this?

You can try using mongodb bulkWrite api:

var ops = []

items.forEach(item => {
    ops.push(
        {
            updateOne: {
                filter: { _id: unique_id },
                update: {
                    $set: { fields_to_set_if_exists },
                    $setOnInsert: { fileds_to_insert_if_does_not_exist }
                },
                upsert: true
            }
        }
    )
})

db.collections('collection_name').bulkWrite(ops, { ordered: false });

I don't believe that you can update an entire array of documents at the same time. Therefore, you would have to update each item in the array individually.

items.forEach((item) => {
   db.items.update({_id: item._id}, item, {upsert: true}, (err, task) => {
           if (err) {
             console.log(err);
           }
   });
}

The {upsert: true} option will update if a record exists and insert if not.

What are you looking for is an upsert, not an insert. It can be done by the following code:

db.collection.update(
   <query>,
   <updates>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>
   }
)

Query will search for a document using the parameters of the query, if it finds, it will update the fields mentioned in . If it doesn't find, it will insert a new document with the fields and values of .

The last object (with multiple fields), contains a field to say if an upsert is desired and one called "multi" to say if an update on multiple documents is desired.

For example:

db.items.update({name:"item1"},{$set:{price:20}},{upsert:true}) 

This will search for a document with the name "item1" and set its price to 20. If it doesn't find, it will create a new one with price 20.

One thing to be noticed though is:

If you don't use the tag $set on the fields, it will substitute the whole document.

Supposing you have a document like this:

{_id:"1234",name:"item1",price:10}

If you run the following two queries:

db.items.update({name:"item1"},{$set:{price:20}},...)

and

db.items.update({name:"item1"},{price:20},...)

it will yeld different results:

First one:

{_id:"1234",name:"item1",price:20}

Second one:

{_id:"1234",price:20}

If you don't call $set , it will change the whole document.

More information on the manual:

https://docs.mongodb.com/manual/reference/method/db.collection.update/

Hope my answer was helpful

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