Mongodb,使用选定的文档值使用单个操作更新同一文档中的字段

Posted

技术标签:

【中文标题】Mongodb,使用选定的文档值使用单个操作更新同一文档中的字段【英文标题】:Mongodb, use selected document value to update field in same document using single operation 【发布时间】:2022-01-19 18:25:08 【问题描述】:

假设您正在制作一个简单的待办事项应用程序,并且您的结构如下所示:


[userId]: 
  nextTaskId:3,
  tasks: 
    1: "take out the trash",
    2: "pick up milk"
  

添加任务时,我想使用 nextTaskId 创建一个新记录并增加它。我见过其他使用聚合函数(如 $concat 等)的示例,但这不适合我的用例。

我希望能够在我的更新中引用该字段,例如:

db.tasks.updateOne(_id:5, $inc:nextId:1, $set: "tasks.$nextId":"new task" )

该字段确实增加了,但任务键不是 3,而是 $nextId,我也尝试将其用作值,如下所示:

db.tasks.updateOne(_id:5, $inc:nextId:1, $set: "tasks.3":"$nextId" )

这也不起作用。当然,我可以通过 2 个单独的操作来做到这一点,一个是获取下一个 id 并增加它,另一个是创建新的任务记录,但我希望通过一个操作来完成。

有什么想法吗?

【问题讨论】:

如果您能提供一个具体的 JSON 示例,将会很有帮助。从您的示例中,您似乎正在使用动态值作为字段名称,这通常被认为是一种反模式,建议尽可能重构您的架构。 感谢您阅读问题和反馈。关于具体的 JSON 示例。我在上面有它,我没有输入 BSON 记录 ID,而是将其标记为 [userId]。后来,我有了示例查询,它们是普通的 mongosh 语法。更清楚地说,基本上我试图在我的更新中引用当前记录值,而不必执行两个单独的操作。这是针对并发问题以及性能问题。我已经看到使用聚合 fcns 完成此操作,例如使用 $concate (即全名字段是第一个和最后一个的连接)。 【参考方案1】:

您可以将更新与聚合管道一起使用,以在单个更新语句中实现该行为。使用$objectToArray$arrayToObject 来操作tasks 数组。

db.collection.update(
  _id: 5
,
[
  
    "$addFields": 
      "tasks": 
        "$objectToArray": "$tasks"
      
    
  ,
  
    "$addFields": 
      "nextTaskId": 
        $add: [
          "$nextTaskId",
          1
        ]
      ,
      tasks: 
        "$concatArrays": [
          "$tasks",
          [
            
              k: 
                $toString: "$nextTaskId"
              ,
              // your input for the new task
              v: "next task"
            
          ]
        ]
      
    
  ,
  
    "$addFields": 
      "tasks": 
        "$arrayToObject": "$tasks"
      
    
  
])

这里是Mongo playground 供您参考。

【讨论】:

哇,好的 Mongodb 向导先生。我没有意识到有 $addFields 能力。查看您的代码,它看起来像:1)第一个 $addFields 将任务 obj 转换为一个数组 2)第二个增加 nextTaskId 并添加一个新的数组元素 3)将任务数组转换回一个对象。我猜想简单地向任务 obj 添加一个属性(任务 obj)并不容易,因此使用了数组。很高兴看到如何使用 $[label] 语法轻松引用当前记录值。而且,感谢您为创建游乐场工作区而付出的额外步骤! Ray,有没有一种方法可以简单地将属性添加到“任务”对象,而无需将其转换为数组、执行连接,然后返回对象? 我猜测复杂性是由于您前面提到的动态键。您可以使用该 k,v 构造来解决此问题,以显式创建您要添加的哈希...我想您不能即时执行此操作 @paultman 是的,你是对的。如果可能,我仍然建议您更改架构。例如,如果你有一个简单的字符串数组,你可以在里面简单地$push new task。此外,从我们在这里收到的当前上下文来看,我认为没有必要维护 taskId。您可能需要重新考虑您的架构或补充更多上下文以供我们查看。 mongoplayground.net/p/_e6saZMWwYI 在那里我硬编码了密钥,我希望我可以使用,“$nextTaskId”

以上是关于Mongodb,使用选定的文档值使用单个操作更新同一文档中的字段的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB——文档操作(更新文档)

MongoDB:如何使用单个命令更新多个文档?

Mongodb crud操作

MongoDB命令查找单个文档并在更新中有条件语句

《MongoDB入门教程》第16篇 文档更新之$min/$max操作符

《MongoDB入门教程》第16篇 文档更新之$min/$max操作符