Search code examples
javascriptnode.jsjsonmongodbmongoimport

Get result of Documents updated from mongoimport


I'm upserting Documents into a Collection using mongoimport. I'm using shelljs to just run the actual mongoimport command the same way it'd be run through a CLI.

E.g. mongoimport docs.json -d DB -c Collection --jsonArray --upsertFields=foo,bar This just outputs the # of Documents updated - but doesn't give any further details on what exactly was changed.

However, I need to be able to see which documents were actually updated/inserted and then do something with these results. I would've thought there'd be some way to get the resulting Object IDs of these documents (perhaps through some -v verbose flag) - but upon doing research, it surprisingly seems that there is no way.

Does anybody know how to get the updated Documents using mongoimport? If it's truly not possible, is there some way to do this using Mongoose? Also, is there any way to check a diff of what exactly was updated on a Document i.e. what fields changed on an upsert? Thanks!


Solution

  • I don't think it's possible to get such information from a bulk operation.

    Using Mongoose, you'll have to iterate through every document and compare the current document and the new document to get the fields that are different. You can either:

    1. Make use of document.modifiedPaths() or document.directModifiedPaths() by getting the diff before you update each document
    const doc = await MyModel.findById(newDoc._id) // or .findOne for other upsert query conditions
    if (doc) {
      const { foo, bar } = newDoc // assuming foo, are are top level fields
      doc.set({ foo, bar })
      const modifiedPaths = doc.directModifiedPaths() // should work if foo, bar are not objects
    } else {
      // no previous doc, insert...
      await MyModel.create(newDoc)
    }
    
    
    1. Compare by yourself
    const { foo, bar } = newDoc
    const doc = await MyModel.findByIdAndUpdate(newDoc._id, { $set: { foo, bar } }, { new: false, upsert: true })
    // or .findOneAndUpdate for other upsert query conditions
    /* since we passed new: false, the operation will return the original document or null if not exists */
    
    const { foo: newFoo, bar: newBar } = doc
    // compare foo & newFoo, bar & newBar