【问题标题】:MongoDB - Update parts of objectMongoDB - 更新部分对象
【发布时间】:2022-07-23 09:59:04
【问题描述】:

我有一个集合,用于存储每个执行流程的文档。 每个流程都包含“流程”,每个流程都包含步骤。 所以我最终得到了一个“流”集合,其中包含如下所示的文档:

{
   "name" : "flow1",
   "description" : "flow 1 description",
   "processes" : [
    {
      "processId" : "firstProcessId",
      "name" : "firstProcessName",
      "startedAt" : null,
      "finishedAt" : null,
      "status" : "PENDING", 
       "steps" : [
        {
         "stepId" : "foo",               ​
         ​"status" : "PENDING",
         ​"startedAt" : null, 
         ​"finishedAt" : null 
        },
        {
         "stepId" : "bar",​
         ​"status" : "PENDING",
         ​"startedAt" : null, 
         ​"finishedAt" : null 
        }
        ...
      ​]
    },
    {
      "processId" : "secondProcessId",
      "name" : "secondProcessName",
      "startedAt" : null,
      "finishedAt" : null,
      "status" : "PENDING", 
       "steps" : [
        {
         "stepId" : "foo",               ​
         ​"status" : "PENDING",
         ​"startedAt" : null, 
         ​"finishedAt" : null 
        },
        {
         "stepId" : "xyz",​
         ​"status" : "PENDING",
         ​"startedAt" : null, 
         ​"finishedAt" : null 
        }
        ...
      ​]
    }
}

这里有几点注意事项: 每个流程包含许多流程 每个进程至少包含一个步骤,在不同的进程中可能会出现相同id的步骤(id是程序员指定的),

它可能类似于“从数据库中给我带来一些东西的步骤”,所以这是我系统中的一种可重用组件。

现在,当应用程序运行时,我想调用 DAO 的方法,例如 “startProcess”、“startStep”。

所以我想知道给定 processId 和步骤的开始步骤的正确查询是什么。

给定流程 ID 和流程 ID,我可以成功地将流程描述更新为“正在运行”:

db.getCollection('flows').updateOne({"name" : "flow1", "processes" : {$elemMatch : {"processId" : "firstProcessId"}}}, {$set: {"processes.$.status" : "RUNNING"}})

但是我不知道如何在给定 flowId、process Id 和 step Id 的情况下更新步骤状态,看起来它不允许路径中有多个“$”符号:

所以,这不起作用:

db.getCollection('flows').updateOne({"name" : "flow1", "processes" : {$elemMatch : {"processId" : "firstProcessId"}}, "processes.steps.stepId" : {$elemMatch : {"stepId" : "foo"}}}, {$set: {"processes.$.steps.$.status" : "RUNNING"}})

实施此类更新的最佳方式是什么?

【问题讨论】:

    标签: java mongodb mongodb-query mongodb-update


    【解决方案1】:

    要更新多级嵌套数组中的文档,您需要$[<identifier>] 过滤位置运算符和arrayFilters

    并且可以删除匹配运算符中的processesprocesses.steps.stepId 过滤器,因为过滤器在arrayFilters 中执行。

    db.collection.update({
      "name": "flow1"
    },
    {
      $set: {
        "processes.$[process].steps.$[step].status": "RUNNING"
      }
    },
    {
      arrayFilters: [
        {
          "process.processId": "firstProcessId"
        },
        {
          "step.stepId": "foo"
        }
      ]
    })
    

    Sample Mongo Playground


    参考

    Update Nested Arrays in Conjunction with $[]

    【讨论】:

      【解决方案2】:

      正如你提到的,它不适用于多个数组,直接来自docs

      位置 $ 运算符不能用于遍历多个数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为 $ 占位符的替换是单个值

      我建议您改用arrayFilters,它的行为更加清晰,尤其是在使用嵌套结构时:

      db.collection.updateMany(
      {
        "name": "flow1",
        "processes.processId": "firstProcessId",
        "processes.steps.stepId": "foo"
      },
      {
        $set: {
          "processes.$[process].steps.$[step].status": "RUNNING"
        }
      },
      {
        arrayFilters: [
          {
            "process.processId": "firstProcessId"
          },
          {
            "step.stepId": "foo"
          }
        ]
      })
      

      Mongo Playground

      【讨论】:

        猜你喜欢
        • 2017-01-23
        • 1970-01-01
        • 2012-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        相关资源
        最近更新 更多