MongoDB中含数组对象的集合与另一集合关联查询问题
解决MongoDB聚合查询中数组关联替换的问题
问题分析
原查询的核心问题在于:当$lookup使用localField: "data.animal"时,MongoDB会将data数组内所有animal字段的值作为一个整体数组,去匹配animal集合的_id,返回所有匹配结果到doc数组;后续$unwind拆分doc后,$project中直接赋值data.animal: "$doc.name"会覆盖整个data数组里所有元素的animal字段,导致每个拆分后的文档中data数组的所有animal值完全相同,最终生成重复的父文档。
正确的聚合查询
db.data.aggregate([ // 拆分data数组,让每个元素独立处理 { "$unwind": "$data" }, // 关联animal集合,匹配单个animal ID { "$lookup": { "from": "animal", "localField": "data.animal", "foreignField": "_id", "as": "animalInfo" } }, // 拆分关联得到的数组(每个data元素仅匹配一个animal,数组长度为1) { "$unwind": "$animalInfo" }, // 替换data.animal为动物名称,保留place字段 { "$project": { "_id": 1, "data.place": 1, "data.animal": "$animalInfo.name" } }, // 按原文档_id分组,将拆分的data元素合并回数组 { "$group": { "_id": "$_id", "data": { "$push": "$data" } } } ])
执行步骤说明
$unwind: "$data":将data数组拆分为单个文档,每个文档包含原_id和data数组的一个元素,确保每个动物ID能单独关联匹配。$lookup:针对每个拆分后的data.animal值,关联animal集合获取对应名称,结果存入animalInfo数组。$unwind: "$animalInfo":因每个data.animal仅匹配一个动物文档,拆分长度为1的数组以便后续取值。$project:重新构造data字段,将animal替换为animalInfo.name,保留place和原_id。$group:按原文档_id分组,用$push将拆分后的data元素重新合并为数组,还原期望的结构。
验证结果
执行上述查询后,将得到目标结果:
[ { "_id": "8e7b3fa0-4230-448c-8f70-1d7300632834", "data": [ { "animal": "Dog", "place": "Chennai" }, { "animal": "Cat", "place": "Kolkata" } ] } ]
内容的提问来源于stack exchange,提问作者Md Enayat
相关产品推荐
相关产品推荐

