Mongoose findOneAndUpdate Upsert _id null?

前端 未结 8 395
生来不讨喜
生来不讨喜 2021-01-01 12:57

I\'d like to have a single method that either creates or updates a document for a policy. Searching and trying different techniques like this one, I have come up with a nul

相关标签:
8条回答
  • 2021-01-01 13:12

    Thanks to JohnnyHK for a helpful answer above. I came up with a one-liner since it's used so frequently:

    query = args._id ? { _id: args._id } : { _id: new ObjectId() };
    

    It relies on the following require:

    const ObjectId = require('mongodb').ObjectID;
    
    0 讨论(0)
  • 2021-01-01 13:14

    Since we can now add default properties while destructuring objects in JavaScript, in the case that we are checking to see if a document exists, I find this the easiest way to either query via an existing _id or create a new one in the same operation, avoiding the null id problem:

    // someController.js using a POST route

    async function someController(req, res) {
      try {
      const {
        // the default property will only be used if the _id doesn't exist
        _id: new mongoose.Types.ObjectId(),
        otherProp,
        anotherProp
      } = req.body;
      const createdOrUpdatedDoc = await SomeModel.findOneAndUpdate(
        {
          _id
        },
        {
          otherProp,
          anotherProp
        },
        {
          new: true,
          upsert: true
        }
      ).exec();
      return res.json(201).json(createdOrUpdatedDoc);
      } catch (error) {
        return res.json(400).send({
          error,
          message: "Could not do this"
        })
      }
    }
    
    0 讨论(0)
  • 2021-01-01 13:17

    I had this same problem and couldn't figure out a way to get it to work. I ended up writing my own upsert method like so....

    var upsert = function(model, data, f){
      if (!data._id) {
        model.create(data, f);
      } else {
        var id = data._id;
        delete data._id;
        model.findOneAndUpdate({_id: id}, data, f);
      }
    }
    

    That allows me to call it for any of my models with one line of code...

    upsert(Team, team, f);
    

    There might be a better way to do it, but this is working for me. I can do updates and inserts and I don't get a null _id on insert.

    0 讨论(0)
  • 2021-01-01 13:22

    null is a valid _id value in MongoDB, so if you don't want it used in new docs you must ensure that a null value is replaced with a new ObjectID in query:

    var query = {_id: plcy._id};
    if (!query._id) {
        query._id = new mongoose.mongo.ObjectID();
    }
    
    // the rest stays the same...
    
    0 讨论(0)
  • 2021-01-01 13:22

    I am not using Mongoose, but I run into similar issue with MongoDB. For Upsert action when new object was inserted the MongoDB was setting null to _id.

    I was calling:

    findOneAndUpdate({my_id:'my_unique_id'}, obj, {upsert: true})
    

    where obj._id was undefined.

    The problem was that _id was present on list of keys Object.keys(obj). I found that I was assigning obj._id = some_variable, where some_variable was undefined, and that was causing _id to appear on a list of keys.

    I applied workaround by calling right before upsert:

    if (_.isUndefined(obj._id)) {
      delete obj._id;
    }
    
    0 讨论(0)
  • 2021-01-01 13:26

    Try setting 'new' parameter to true:

    { upsert: true, new: true }
    

    More info: https://github.com/Automattic/mongoose/issues/2939

    0 讨论(0)
提交回复
热议问题