Shamoon Shamoon - 5 months ago 69
Node.js Question

How can I upsert using Mongoose based on _id?

When I do this:

client_id = req.param("client_id") ? null
client =
name: req.param "clientName"
status: 'active'

Client.update {_id: client_id}, client, {upsert: true}, (err, updRes) ->
if err
res.json
error: "Couldn't create client"
else
res.json client


It will create a new client record, except with a
null
_id
field. I assume that's because the insert part of the upsert looks to the
query
to create the document. How can I do it so that if no doc is found, then insert a new
ObjectId
?

Answer

Not sure if you have figured this one out yet, but in case you don't want to run into trouble with unique key constraints like Mustafa mentioned above, the way I've done it is by using mongoose's findByIdAndUpdate:

// require mongoose

client_id = req.param("client_id") ? new mongoose.Types.ObjectId
client =
  name: req.param "clientName"
  status: 'active'

Client.findByIdAndUpdate client_id, client, {upsert: true}, (err, updRes) ->
  if err
    res.json
      error: "Couldn't create client"
  else
    res.json client

I've never written CoffeeScript, so forgive me if some of that syntax is wrong, but I think it should be fairly obvious what I'm trying to do.

One thing to notice is that you need to make sure client_id is neither an empty string (as that would cause an 'Invalid ObjectID' error) nor null (because mongoose seems infer the new document's id from the one you're querying for). In case it is, I create a new ObjectId, which will cause the query to miss and therefore create a new document with that ID since I pass {upsert: true}.

This seems to have solved the problem for me.