Search code examples
mongodbmongoosemongoose-schemamongoose-web-server

Mongoose Update By Passing In Array of Documents


Would functionality similar to this be possible:

let Item = mongoose.model('Item')
let updatedItems = [updatedItem1, updatedItem2]
let updatedItemIds = [updatedItem1._id, updatedItem2._id]

Item.updateMany({_id: {$in: updatedItemIds }}, updatedItems) // this wont work

Which would be similar to:

updatedItems.forEach( item => {
    Item.updateOne({_id: item._id}, item) 
})

I am trying to avoid calling the server multiple times and I know there is a bulkWrite option and I could do something like this:

bulk = []
updatedItems.forEach( item => { 
  let updateDoc = {
    'updateOne': {
      'filter': { '_id': item._id },
      'update': item,
      'upsert': false
     }
  }  
  bulk.push(updateDoc)
})
Item.collection.bulkWrite(bulk)

But this feels inefficient since it seems like it will need to load each custom query, although I am not knowledgeable on bulkWrite under the hood. I just wanted to ask if bulkWrite is only option here.

EDIT: I know the first query above will not work, but it is to show what functionality I am looking for - pass in updated objects into Mongoose and for those objects to be matched to their respective documents and updated.


Solution

  • As of writing, bulk write is only way of dynamically updating multiple documents at once in Mongoose (unique update for each document within one query). A complex Mongo aggregate could also accomplish updating each document differently in one query, but its performance would suffer per filter or conditional check you add in the aggregate.

    I found performance of bulk write to be better than multiple Mongoose updates:

    bulk = []
    updatedItems.forEach( item => { 
      let updateDoc = {
        'updateOne': {
          'filter': { '_id': item._id },
          'update': item,
          'upsert': false
         }
      }  
      bulk.push(updateDoc)
    })
    Item.collection.bulkWrite(bulk)