首页 > 解决方案 > MongoDB 聚合填充/替换 ObjectId 数组

问题描述

我有以下 MongoDB 结构:

campaign:{
  _id: '5e4eee638552043e60e5073b',
  name: 'Test campaign',
  partners: [
    {
      _id: '5e4fa9fbbdeb4a5878ac2a35',
      options: [Object],
      partner: '5e4e9bc2101ecb2e8764190c',
    },
    {
      _id: '5e4ff7c6e54b6d676d97b7a6',
      options: [Object],
      partner: '5e4ff51c23f44266a8add39e',
    }
  ]
}

使用以下aggregate函数,我可以查找每个合作伙伴的 ID 并添加到新数组中:

{
  $lookup:
  {
    from: 'campaigns',
    let: { campaign: '$campaign' },
    pipeline: [
      { $match: { $expr: { $and: [{ $eq: ['$_id', '$$campaign'] }] } } },
      {
        $lookup:
          {
            from: 'partners',
            let: { partner: '$partner.partner' },
            pipeline: [
              { $match: { $expr: { $in: ['$_id', '$$partner'] } } },
              { $project: { _id: 1, name: 1 } }
            ],
            as: 'partner1'
          }
        },
        {
          $project: {
            _id: 1, shortName: 1, userInterface: 1, options: 1, check: 1, description: 1, partner: 1, partner1: 1 } }
    ],
    as: 'campaign'
  }
}

这是新的输出:

campaign: {
  _id: '5e4eee638552043e60e5073b',
  name: 'Test campaign',
  partners: [
    ...
  ],
  partner1: [
    { _id: '5e4e9bc2101ecb2e8764190c', name: '123' },
    { _id: '5e4ff51c23f44266a8add39e', name: '456' }
  ]
}

但我想要做的是将_id合作伙伴数组中的每个元素替换为完整的合作伙伴对象。

合作对象:

partner
{ 
  _id: '5e4e9bc2101ecb2e8764190c',
  name: '123',
  etc: ...
},
{
  _id: '5e4ff51c23f44266a8add39e',
  name: '456'
  etc: ...
}

这是最终对象的样子:

[
  {
    "campaign": [
      {
        "partner": [
          {
            "_id": "5e4eee638552043e60e5073b",
            "options": [
              {}
            ],
            "partner": {
                "_id": "5e4e9bc2101ecb2e8764190c",
                "name": "123"
            }
          }
        ]
      }
    ]
  }
]

标签: arraysmongodbaggregate

解决方案


您需要添加额外的 3 个阶段:

db.collection.aggregate([
  //your $lookup,
  {
    $unwind: "$campaign"
  },
  {
    $project: {
      _id: 1,
      "campaign.partner": {
        $map: {
          input: "$campaign.partner",
          as: "partner",
          in: {
            $let: {
              vars: {
                partner1: {
                  $filter: {
                    input: "$campaign.partner1",
                    cond: {
                      $eq: [
                        "$$partner.partner",
                        "$$this._id"
                      ]
                    }
                  }
                }
              },
              in: {
                // we merge partner[i] with partner1[j]
                $mergeObjects: [
                  "$$partner",
                  {
                    partner: {
                      $arrayElemAt: [
                       "$$partner1",
                        0
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      campaign: {
        $push: "$campaign"
      }
    }
  }
])

Mongo游乐场


推荐阅读