【问题标题】:Move data from one array to another array in the same document将数据从一个数组移动到同一文档中的另一个数组
【发布时间】:2022-01-04 14:18:11
【问题描述】:

我需要在同一个文档中将一个数组元素从一个数组移动到另一个数组,并从原来的数组中删除该元素。

// Document
{
   _id: ObjectId("67dc90594947be000838f7a7"),
   persons: [
        {
           personId: "61cd90594947be000838f7c1",
           name: "John Doe",
           employment: [
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Full time",
                  salary: 1010101
               }
           ]
        },
        {
           personId: "61cd90594947be000838f7c2",
           name: "Jane Austin",
           employment: [
               {
                  employmentId: "61cd9059494abe000738f7c1",
                  type: "Part time",
                  salary: 11011111
               }
           ]
        },
   ]
}

我需要将一个雇佣元素从 John Doe 移到 Jane Austin,并且这两个人都在同一个文档中。我需要从 John Doe 中删除移动的元素。 employmentId 用于确定要调动的工作。而personId是用来标识从哪个人那里移动到哪个人那里的。

负载示例

const updatePayload = {
   fromPerson: "61cd90594947be000838f7c1",
   toPerson: "61cd90594947be000838f7c2",
   employmentId: "61cd9059494abe000838f7c8",
}

预期结果

// employment from John Doe is moved to Jane Austin
{
   _id: ObjectId("67dc90594947be000838f7a7"),
   persons: [
        {
           personId: "61cd90594947be000838f7c1",
           name: "John Doe",
           employment: [ ]
        },
        {
           personId: "61cd90594947be000838f7c2",
           name: "Jane Austin",
           employment: [
               {
                  employmentId: "61cd9059494abe000738f7c1",
                  type: "Part time",
                  salary: 11011111
               },
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Full time",
                  salary: 1010101
               }
           ]
        },
   ]
}

【问题讨论】:

    标签: node.js arrays mongodb mongodb-query aggregation-framework


    【解决方案1】:

    这是 Mongo 4.4 版的工作示例,我们的策略是首先匹配我们要移动的 employment,然后相应地更新每个 persons,我会说在 Mongo v5.0 中这样做+ 会更干净,因为我们可以使用$getField,这将使流水线更新的前两个阶段更加简单。

    话虽如此,这里是代码示例:

    const updatePayload = {
       fromPerson: "61cd90594947be000838f7c1",
       toPerson: "61cd90594947be000838f7c2",
       employmentId: "61cd9059494abe000838f7c8",
    }
    
    db.collection.update({},
    [
      {
        $set: {
          tmpPerson: {
            $arrayElemAt: [
              {
                $filter: {
                  input: "$persons",
                  as: "person",
                  cond: {
                    $eq: [
                      "$$person.personId",
                      updatePayload.fromPerson
                    ]
                  }
                }
              },
              0
            ]
          }
        }
      },
      {
        $set: {
          tmpEmployment: {
            $arrayElemAt: [
              {
                $filter: {
                  input: "$tmpPerson.employment",
                  as: "employment",
                  cond: {
                    $eq: [
                      "$$employment.employmentId",
                      updatePayload.employmentId
                    ]
                  }
                }
              },
              0
            ]
          }
        }
      },
      {
        $set: {
          persons: {
            $map: {
              input: "$persons",
              as: "person",
              in: {
                $switch: {
                  branches: [
                    {
                      case: {
                        $eq: [
                          "$$person.personId",
                          updatePayload.fromPerson
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$person",
                          {
                            employment: {
                              $filter: {
                                input: "$$person.employment",
                                as: "employment",
                                cond: {
                                  $eq: [
                                    "$$employment.employmentId",
                                    updatePayload.employmentId
                                  ]
                                }
                              }
                            }
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$person.personId",
                          updatePayload.toPerson
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$person",
                          {
                            employment: {
                              $concatArrays: [
                                "$$person.employment",
                                [
                                  "$tmpEmployment"
                                ]
                              ]
                            }
                          }
                        ]
                      }
                    }
                  ],
                  default: "$$person"
                }
              }
            }
          }
        }
      },
      {
        $unset: [
          "tmpPerson",
          "tmpEmployment"
        ]
      }
    ])
    

    Mongo Playground

    最后要注意的是,此管道假定输入正确存在,否则会将null 添加到就业数组中。如果不是这种情况,那么您应该添加一些保护。

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 2018-02-05
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2021-10-25
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多