MongoDB:推送到嵌套数组或更新现有数组元素

MongoDB: Push to a nested array or update the existing array element

我有一份格式如下的文件:

// 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: "61cd9059494abe000838f7c8",
                  type: "Part time",
                  salary: 11011111
               }
           ]
        },
   ]
}

我需要一个查询,如果就业匹配 employmentId 则更新 persons 内的现有 employment 或将新元素推送到数组。

例如

案例一:更新就业

// update payload
// This employment id is the first employment of John Doe
// So the first employment will be updated
{
    personId: "61cd90594947be000838f7c1",
    employmentId: "61cd9059494abe000838f7c8",
    frequency: "weekly"
}
// The updated document
{
   _id: ObjectId("67dc90594947be000838f7a7"),
   persons: [
        {
           personId: "61cd90594947be000838f7c1",
           name: "John Doe"
           employment: [
               // This is updated employment
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Full time",
                  salary: 1010101,
                  frequency: "weekly"
               }
           ]
        },
        {
           personId: "61cd90594947be000838f7c2",
           name: "Jane Austin"
           employment: [
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Part time",
                  salary: 11011111
               }
           ]
        },
   ]
}

案例二:推新就业到数组

// update payload
// This employment id is not in John Doe
// So the data will be pushed to array
{
    personId: "61cd90594947be000838f7c1",
    employmentId: "61cd9059494abe000738f7c1",
    frequency: "weekly"
}
// The updated document
{
   _id: ObjectId("67dc90594947be000838f7a7"),
   persons: [
        {
           personId: "61cd90594947be000838f7c1",
           name: "John Doe"
           employment: [
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Full time",
                  salary: 1010101
               },
               /// This is newly added employment
               {
                  employmentId: "61cd9059494abe000738f7c1",
                  frequency: "weekly"
               }
           ]
        },
        {
           personId: "61cd90594947be000838f7c2",
           name: "Jane Austin"
           employment: [
               {
                  employmentId: "61cd9059494abe000838f7c8",
                  type: "Part time",
                  salary: 11011111
               }
           ]
        },
   ]
}

对于非嵌套数组,我得到了 .

同样,该方法与上一个问题的更新类似,我们必须迭代每个数组并确定元素是否匹配。

请注意,此答案不处理问题中不需要的情况 #3,即一个人不存在的情况。根据输入,我认为这个人存在是合理的。

const input = {
    personId: "61cd90594947be000838f7c1",
    employmentId: "61cd9059494abe000738f7c1",
    frequency: "weekly"
};

const employmentInput = {
    employmentId: "61cd9059494abe000738f7c1",
    frequency: "weekly"
};

db.collection.update({},
[
  {
    $set: {
      persons: {
        $map: {
          input: "$persons",
          as: "person",
          in: {
            $cond: [
              {
                $eq: [
                  input.personId,
                  "$$person.personId"
                ]
              },
              {
                $mergeObjects: [
                  "$$person",
                  {
                    employment: {
                      $cond: [
                        {
                          $in: [
                            input.employmentId,
                            "$$person.employment.employmentId"
                          ]
                        },
                        {
                          $map: {
                            input: "$$person.employment",
                            as: "employment",
                            in: {
                              $cond: [
                                {
                                  $eq: [
                                    input.employmentId,
                                    "$$employment.employmentId"
                                  ]
                                },
                                {
                                  $mergeObjects: [
                                    "$$employment",
                                    employmentInput
                                  ]
                                },
                                "$$employment"
                              ]
                            }
                          }
                        },
                        {
                          $concatArrays: [
                            "$$person.employment",
                            [
                              employmentInput
                            ]
                          ]
                        }
                      ]
                    }
                  }
                ]
              },
              "$$person"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground