如何基于 _id 使用 Mongoose 进行 upsert 操作?

3
当我这样做时:

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

它将创建一个新的客户记录,但是 _id 字段为 null。我认为这是因为 upsert 的插入部分查找 query 来创建文档。如何才能做到如果没有找到文档,就插入一个新的 ObjectId

2个回答

8

不确定您是否已经解决了这个问题,但是如果您不想遇到像Mustafa上面提到的唯一键约束的麻烦,我所做的方法是使用mongoose的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

我从未编写过CoffeeScript,因此如果某些语法错误,请谅解,但我认为我试图做的事情应该是相当明显的。
需要注意的一件事是,您需要确保client_id既不是空字符串(因为这会引起“无效ObjectID”错误),也不为null(因为mongoose似乎会将新文档的id推断出来从您查询的文档中)。如果是这种情况,我会创建一个新的ObjectId,这将导致查询未命中,因此传递{upsert: true}将创建具有该ID的新文档。这对我来说似乎已经解决了问题。

在Mongoose v 4.0之后,您需要显式地将new选项设置为true,因为在4.0之前的默认值为true,但在4.0之后为false。请参考此Stack Overflow问题这些发布说明 - steampowered

2
只需在客户端调用Mongoose的save方法,Mongoose会自行判断是更新还是插入操作:
client_id = req.param("client_id") ? null
client_data =
  name: req.param "clientName"
  status: 'active'
  _id: client_id

client = new Client(client_data)
client.save (err) ->
  if err
    res.json
      error: "Couldn't save client"
  else
    res.json client

注意:客户端是一个Mongoose模型。

不需要再使用upsert了吗? - Shamoon
1
我可以告诉你,我在我的代码中实际使用过这个方法,无论是插入还是更新,都很有效,所以不需要使用upserts。感谢Mongoose ODM :) - alessioalex
如果client_id为null,这将使用新的_id保存吗? - Shamoon
看起来这个问题已经解决了?我现在可以得到一个失败的唯一值。 - binarygiant
不用理会,不会像我想的那样发生。 - binarygiant
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接