0

I'm using mongoose to handle my DB queries. I'm trying to update a set of records entirely using this method. Mode code looks like this:

// prepare database query
const filter = { type: 'company' };
const update = req.body.payload; // payload contains the array of objects (i.e. updated records)
const options = { new: true, runValidators: true }

// find and update the taxonomy record
await Taxonomy.updateMany(filter, update, options);

But whenever I run this query I'm getting following error in the console:

Error [MongooseError]: Invalid update pipeline operator: "_id"

I suppose there is something wrong in my update payload. The req.body.payload looks like this:

[
    {
        _id: '5ef3d08c745428001d92f896',
        type: 'company',
        name: 'Company Size',
        __v: 0
    },
    {
        _id: '5ef3cdc5745428001d92f893',
        type: 'company',
        name: 'Company Industry',
        __v: 0
    }
]

Can you please tell me what actually is wrong here?

Faisal Khurshid
  • 1,869
  • 3
  • 21
  • 27
  • You can do a `console.log` on the value of `req.body.payload` and see if it is a valid _update_ . Also, see [Mongoose updateMany()](https://mongoosejs.com/docs/api.html#model_Model.updateMany). – prasad_ Jun 25 '20 at 07:14
  • @prasad_ I've updated my question with the value of `req.body.payload`, please take a look. – Faisal Khurshid Jun 25 '20 at 07:31
  • The syntax and usage of [updateMany](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/index.html). Also, see this answer: [Update many in mongoose](https://stackoverflow.com/questions/54992810/update-many-in-mongoose). – prasad_ Jun 25 '20 at 08:53
  • @prasad_ Thanks, I've seen the docs, according to the docs, `updateMany()` is expecting `req.body.payload` value as a single document which contains the "update operators". However, all I'm trying to do is to change the order of documents in MongoDB collection, I'm not actually updating any specific field value. It does not seems to be possible this way. Can you suggest any other approach to achieve this? – Faisal Khurshid Jun 25 '20 at 09:04
  • Why are you trying to change the order of documents in the collection? When you query, you can sort the documents as you need. – prasad_ Jun 25 '20 at 09:13
  • @prasad_ The issue is, I'm sorting and displaying documents based on it's actual order in the collection not by any specific field. So, the order of documents is important. – Faisal Khurshid Jun 25 '20 at 09:16
  • 1
    Your payload is an array of objects. The update is to be a document _or_ a pipeline. – prasad_ Jun 25 '20 at 09:21
  • @prasad_ So, I guess it is not possible with mongoDB to change order of the documents. In that case, I'll have to look for other alternatives (e.g. save the order of documents in a field to sort it later, based on that). Thanks for your help. – Faisal Khurshid Jun 25 '20 at 09:33
  • I had a similar problem, but I was setting the same value for all the documents that match the filter. There were two things wrong with my code: 1) I needed to include the fields I wanted to update in the Mongoose schema. and 2) The update object needed to be a [$set update operator](https://docs.mongodb.com/manual/reference/operator/update/set/#mongodb-update-up.-set) – Alphonso77 Mar 16 '22 at 19:31
  • updateMany() takes an array of objects as parameter, so try putting [ ] inside the function – Shashank KR Sep 15 '22 at 19:26

1 Answers1

0

This is not the right usage of updateMany() - it is aimed to update many documents with a single change.

To update many documents use bulkwrite() (docs) :

async function myUpdateMany(Model, objectsArray) {
    try {
        let ops = []
        for (let obj of (objectsArray || [])) {
            ops.push({
                    updateOne: {
                        filter: { platformId: obj.platformId },
                        update: obj,
                        upsert: false, // set "true" if you want to add a new document if it doesn't exist
                    }
            })
        }
        Model.bulkWrite(ops, { ordered: false });
    } catch (err) {
        throw Error("myUpdateMany error: " + err)
    }
}

Regarding runValidators, according to this, it seems to work by default.

o.z
  • 1,086
  • 14
  • 22