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

Posted

技术标签:

【中文标题】如何使用基于 _id 的 Mongoose 进行 upsert?【英文标题】:How can I upsert using Mongoose based on _id? 【发布时间】:2012-01-19 09:40:55 【问题描述】:

当我这样做时:

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

它将创建一个新的客户记录,但 null _id 字段除外。我认为这是因为 upsert 的插入部分看起来是 query 来创建文档。我该怎么做才能在没有找到文档的情况下插入一个新的ObjectId

【问题讨论】:

【参考方案1】:

不确定你是否已经想出了这个,但如果你不想遇到像上面提到的 Mustafa 这样的唯一键约束的问题,我这样做的方法是使用猫鼬的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”错误)也不是空字符串(因为 mongoose 似乎从您正在查询的文档中推断出新文档的 id为了)。如果是这样,我会创建一个新的 ObjectId,这将导致查询丢失,因此会创建一个具有该 ID 的新文档,因为我通过了 upsert: true。

这似乎为我解决了问题。

【讨论】:

在 Mongoose v 4.0 之后,您需要将 new 选项显式设置为 true,因为 4.0 之前的默认值是 true,但现在在 4.0 之后是 false。参考this stack overflow question 和these release notes。【参考方案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 模型。

【讨论】:

所以不再需要 upserts 了吗? 我可以告诉你我已经在我的代码中实际使用了它,用于插入和更新,它可以工作,所以不需要 upserts。祝福猫鼬 ODM :) 如果 client_id 为空,是否会使用新的_id 保存? 你能解释更多吗,@Mustafa? 确认这在索引字段上失败。参考:groups.google.com/forum/?fromgroups=#!topic/mongoose-orm/…

以上是关于如何使用基于 _id 的 Mongoose 进行 upsert?的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose - 如何替换 _id 作为主索引?

Mongoose - 如何防止 mongoose 在模型实例化时创建 _id

mongoose 和 typescript 如何自动将 '_id' 转换为 'id'?

使用 Mongoose.js 按嵌套数组中的字段排序

如何将 Mongoose 对象与 JSON 对象进行比较?

如何在 Mongoose 中将 _id 设置为 db 文档?