简体   繁体   中英

mongoose plugin doesn't hook on findOneAndUpdate

I setup a mongoose schema like so:

 const expertSchema = new mongoose.Schema({ firstName: { type: String, required: true, }, lastName: { type: String, required: true, }, contactMethods: { type: [ContactMethod.schema], } }) expertSchema.plugin(autoIncrement.plugin, { model: 'EXP-', startAt: 1, prefix: 'EXP-' }); const Expert = mongoose.model('Expert', expertSchema); const contactMethodsSchema = new mongoose.Schema({ type: { type: String, required: true, }, value: { type: String, required: true, }, preferred: { type: Boolean } }); contactMethodsSchema.plugin(autoIncrement.plugin, { model: 'CON-', startAt: 1, prefix: 'CON-' }); const ContactMethod = mongoose.model('ContactMethod', contactMethodsSchema)

I'm using the mongoose-auto-increment plugin to auto-increment my monogodb document's id's (actually using this fork, but they are basically the same)

I have some code that seeds my dev. db on restart which looks like this:

 const contMethod1 = new models.ContactMethod({ type: 'email', value: "janedoe@acme.org", preferred: false, }); const contMethod2 = new models.ContactMethod({ type: 'phone', value: "+12125550711", preferred: true, }); const expert1 = new models.Expert({ firstName: 'Jane', lastName: 'Doe', contactMethods: [contMethod1, contMethod2] }); expert1.save();

This code works great and I end up with a document that looks like:

 { "_id": "EXP-1", "firstName": "Jane", "lastName": "Doe", "contactMethods": [{ "type": "email", "value": "janedoe@acme.org", "preferred": false, "_id": "CON-1" }, { "type": "phone", "value": "+12125550711", "preferred": true, "_id": "CON-2" } ] }

However when my frontend posts this edited data back to me I get json that looks like:

 { _id: "EXP-1", "contactMethods": [{ "type": "email", "value": "janedoe@acme.org", "preferred": false, "_id": "CON-1" }, { "type": "phone", "value": "+12125550711", "preferred": true, "_id": "CON-2" }, { "type": "whatsapp", "value": "+123456789", "preferred": false } ] }

Now what I want is to update existing embedded documents and/or add new ones if needed. I setup this code for this purpose (I appreciate there is probably a much more intelligent way to implement this, but even so, it sort of "works"):

 req.body.contactMethods.map((_, index) => { if (_._id) { expert = req.context.models.Expert.findOneAndUpdate({ "contactMethods._id": _._id }, { $set: { "contactMethods.$.type": _.type, "contactMethods.$.value": _.value, "contactMethods.$.preferred": _.preferred } }, { useFindAndModify: false, returnOriginal: false, runValidators: true }) } else { expert = req.context.models.Expert.findOneAndUpdate({ "_id": req.user._id, }, { $push: { "contactMethods": _ } }, { useFindAndModify: false, returnOriginal: false, runValidators: true }) } })

Unfortunately, is this scenario my plugin doesn't "trigger" or invoke and I end up with a document updated in the collection which lacks a "_id" property for the newly pushed contactMethod.

Why is my plugin not being called on the findOneAndUpdate call?

I found this question but my plugin doesn't use ES6 syntax. Also I found this comment but the current mongoose documentation doesn't state that anymore so I was kinda hoping maybe they changed/fixed it.

Thanks, (first question. phew..)

I eventually solved (or rather worked around this) by changing my code and splitting up the addition of a new contact method to two operations: findOne and save, like so:

req.body.contactMethods.map((_, index) => {
  if (_._id) {
    expert = req.context.models.Expert.findOneAndUpdate({
      "contactMethods._id": _._id
    }, {
      $set: {
        "contactMethods.$.type": _.type,
        "contactMethods.$.value": _.value,
        "contactMethods.$.preferred": _.preferred
      }
    }, {
      useFindAndModify: false,
      returnOriginal: false,
      runValidators: true
    })
  } else {
    expert = req.context.models.Expert.findOne({
      "_id": req.user._id,
    })
    expert.contactMethods.push(_);
    expert.save({ validateModifiedOnly: true });
  }
})

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