Mongoose:使用当前项目数据更新嵌套数组中的项目

问题描述 投票:0回答:1

集合中有以下文档:

const documents = [
    {
        _id: '1',
        items: [
            {
                type: 'plastic',
                color: 'blue',
                date: '2021-02-01',
                oldValues: [{ color: 'light-blue', date: '2021-01-01' }],
            },
            {
                type: 'plastic',
                color: 'black',
                date: '2021-03-01',
                oldValues: [
                    { color: 'white', date: '2021-01-01' },
                    { color: 'grey', date: '2021-02-01' },
                ],
            },
        ],
    },
    {
        _id: '2',
        items: [
            {
                type: 'plastic',
                color: 'violet',
                date: '2021-02-01',
                oldValues: [{ color: 'pink', date: '2021-01-01' }],
            },
            {
                type: 'wood',
                color: 'black',
                date: '2021-03-01',
                oldValues: [
                    { color: 'white', date: '2021-01-01' },
                    { color: 'orange', date: '2021-02-01' },
                ],
            },
        ],
    },
];

我想在 items 字段中查找包含类型为 Plastic 且颜色为 black 的项目的文档,将该项目的颜色更新为 green,并在 oldValues 中保留当前项目的记录 字段,像这样:

[
    {
        _id: '1',
        items: [
            {
                type: 'plastic',
                color: 'blue',
                date: '2021-02-01',
                oldValues: [{ color: 'light-blue', date: '2021-01-01' }],
            },
            {
                type: 'plastic',
                color: 'green',
                date: '2021-03-01',
                oldValues: [
                    { color: 'white', date: '2021-01-01' },
                    { color: 'grey', date: '2021-02-01' },
                    { color: 'black', date: '2021-03-01' },
                ],
            },
        ],
    },
    {
        _id: '2',
        items: [
            {
                type: 'plastic',
                color: 'violet',
                date: '2021-02-01',
                oldValues: [{ color: 'pink', date: '2021-01-01' }],
            },
            {
                type: 'wood',
                color: 'black',
                date: '2021-03-01',
                oldValues: [
                    { color: 'white', date: '2021-01-01' },
                    { color: 'orange', date: '2021-02-01' },
                ],
            },
        ],
    },
];

为此,我编写并运行了以下查询:

db.collection.update(
    { items: { $elemMatch: { color: 'black', type: 'plastic' } } },
    {
        $set: {
            'items.$[item].color': 'green',
            'items.$[item].date': '2021-04-01',
            'items.$[item].oldValues': {
                $concatArrays: [
                    { $ifNull: ['$items.$[item].oldValues', []] },
                    [{ color: '$items.$[item].color', date: '$items.$[item].date' }],
                ],
            },
        },
    },
    { arrayFilters: [{ 'item.color': 'black', 'item.type': 'plastic' }] },
);

通过此查询,items字段中感兴趣项目的color字段已更新,但oldValues字段被更新项覆盖:

const updatedDocumentsAfterRunningQuery = [
    {
        _id: '1',
        items: [
            {
                color: 'blue',
                date: '2021-02-01',
                oldValues: [{ color: 'light-blue', date: '2021-01-01' }],
                type: 'plastic',
            },
            {
                color: 'green',
                date: '2021-04-01',
                oldValues: {
                    $concatArrays: [
                        { $ifNull: ['$items.$[item].oldValues', []] },
                        [{ color: '$items.$[item].color', date: '$items.$[item].date' }],
                    ],
                },
                type: 'plastic',
            },
        ],
    },
    {
        _id: '2',
        items: [
            {
                color: 'violet',
                date: '2021-02-01',
                oldValues: [{ color: 'pink', date: '2021-01-01' }],
                type: 'plastic',
            },
            {
                color: 'black',
                date: '2021-03-01',
                oldValues: [
                    { color: 'white', date: '2021-01-01' },
                    { color: 'orange', date: '2021-02-01' },
                ],
                type: 'wood',
            },
        ],
    },
];

看起来运算符 $concatArrays 未被 $set 运算符检测到。

这是MongoDb Playground的链接。

我该如何解决这个问题?

mongodb updates
1个回答
0
投票

请尝试一下此代码:

db.collection.aggregate([
  {
    $match: {
      "items.color": "black",
      "items.type": "plastic"
    }
  },
  {
    $set: {
      items: {
        $map: {
          input: "$items",
          as: "item",
          in: {
            $cond: {
              if: {
                $and: [
                  {
                    $eq: [
                      "$$item.color",
                      "black"
                    ]
                  },
                  {
                    $eq: [
                      "$$item.type",
                      "plastic"
                    ]
                  }
                ]
              },
              then: {
                $mergeObjects: [
                  "$$item",
                  {
                    color: "green",
                    date: "2021-04-01",
                    oldValues: {
                      $concatArrays: [
                        {
                          $ifNull: [
                            "$$item.oldValues",
                            []
                          ]
                        },
                        [
                          {
                            color: "$$item.color",
                            date: "$$item.date"
                          }
                        ]
                      ]
                    }
                  }
                ]
              },
              else: "$$item"
            }
          }
        }
      }
    }
  },
  {
    $merge: {
      into: "collection",
      whenMatched: "replace"
    }
  }
])

MondoDb Playground 更新代码

© www.soinside.com 2019 - 2024. All rights reserved.