如何通过MongoDB聚合将同集合文档数据补充到子数组中
MongoDB聚合查询:为数组子项补充完整文档字段
现有items集合,文档结构包含listOfItems数组,数组内的子项仅存储了部分字段(如itemId、color、itemName),需要关联同集合内对应itemId的完整文档,补充name、date、quantity等字段,最终替换原数组为包含完整信息的结构。
聚合查询语句
db.items.aggregate([ // 关联同集合,匹配listOfItems中每个itemId对应的完整文档 { $lookup: { from: "items", localField: "listOfItems.itemId", foreignField: "itemId", as: "matchedItems" } }, // 替换listOfItems为包含完整字段的子项数组 { $addFields: { listOfItems: { $map: { input: "$listOfItems", as: "originalItem", in: { $first: { $filter: { input: "$matchedItems", cond: { $eq: ["$$this.itemId", "$$originalItem.itemId"] } } } } } } } }, // 移除临时关联字段(可选) { $project: { matchedItems: 0 } } ])
各阶段说明
- $lookup:将当前文档
listOfItems中的所有itemId与同集合的itemId做关联,把匹配到的完整文档存入matchedItems临时数组。 - $addFields:通过
$map遍历原listOfItems数组,对每个子项用$filter从matchedItems中筛选出对应itemId的完整文档,$first确保只取唯一匹配结果(需保证itemId为集合唯一标识),直接替换原数组元素。 - $project:移除临时生成的
matchedItems字段,让输出结构更简洁,不需要的话可以省略此阶段。
关键注意点
- 必须保证
itemId是集合内的唯一标识,否则一个itemId对应多个文档会导致匹配结果出现异常。 - 若原
listOfItems子项有需要保留的额外字段,可使用$mergeObjects将原字段与匹配到的完整文档字段合并,例如:
本场景中目标结构不需要原in: { $mergeObjects: [ "$$originalItem", { $first: { $filter: {...} } } ] }itemName,因此直接使用匹配到的完整文档即可。
内容的提问来源于stack exchange,提问作者Eric Pezzulo
相关产品推荐
相关产品推荐

