【问题标题】:Mongo: create if document doesn't exist, otherwise do nothingMongo:如果文档不存在则创建,否则什么也不做
【发布时间】:2021-09-13 12:20:12
【问题描述】:

我有一个 Mongo 集合,它有两个字段,比如说“name”和“randomString”。

我想为一个名称创建一个随机字符串,前提是它不存在。因此,{ name: "SomeName" } 的第一个请求将导致保存,例如{ name: "someName", randomString: "abc" }。第二个请求什么也不做。

这有 mongo 命令吗?我能找到的只有findOneAndUpdatereplaceOne 等东西,它们都支持可选的“upsert”,但他们在匹配时的行为是更新,我希望匹配时的行为什么都不做。

我不是在寻找像 this question 这样的 if-then 解决方案,因为我遇到了竞争条件问题 - 我需要能够同时获取多个请求,而无需更新文档或使任何请求失败。

【问题讨论】:

  • 这能回答你的问题吗? Find one or create with Mongoose
  • { name, randomString: 'abc' } 不是有效的 JSON。您的输入是什么,您期望输出什么?
  • @raina77ow 不是真的,我正在尝试解决此答案无法解决的竞争条件
  • @WernfriedDomscheit 这是一个nodejs对象格式

标签: node.js mongodb mongoose


【解决方案1】:

是的,有一个命令可以做到这一点,你可以使用 $addToSet 方法。 欲了解更多信息,请通过给定的链接:https://docs.mongodb.com/manual/reference/operator/update/addToSet/

PS:如果您对此问题仍有任何疑问,请随时进一步评论。

谢谢

【讨论】:

  • 谢谢,但它不是一个数组,所以我不认为 addToSet 应用
  • 嗨,这也适用于对象我已经尝试过并使用过这个
【解决方案2】:

您可以使用$exists 命令轻松检查randomString 字段,然后在聚合管道中使用$set 来更新该字段。

db.collection.updateMany({"name":someName,"randomString":{$exists: false}},[{$set:{"randomString":"abcd"}}],{upsert:true})

如果条件查询不匹配任何文档,则返回null

注意:聚合管道仅适用于 MongoDB 4.2 及更高版本的 updateMany()

【讨论】:

  • 如果文档不存在,则不会创建新文档。
  • 是的,但是现在它会一遍又一遍地创建一个新文档,因为它找不到与"randomString":{$exists: false}匹配的东西
  • 一遍又一遍地创造是什么意思?如果它没有找到任何文档,除了创建一个新文档之外它不会做任何事情。它取决于搜索查询“name:someName”,所以一旦更新了所有具有该名称的文档,就是这样。
【解决方案3】:

这是我最后找到的解决方案:

CustomerRandomString.findOneAndUpdate(
    { name: "someName" },
    {
      $setOnInsert: { randomString: generateRandomString() },
    },
    { upsert: true },
  );

setOnInsert 运算符仅适用于创建新文档时,这正是我所需要的。

编辑:根据the docs,此解决方案需要在字段上使用unique index,以完全避免重复。

【讨论】:

    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 2019-02-16
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    相关资源
    最近更新 更多