MongoDB新手求助:聚合查询中基于parent_id生成同组name数组
解决MongoDB聚合中按parent_id生成name数组的问题
首先,你当前的聚合逻辑有个关键问题:按$_id分组的话,每个分组只能拿到单个文档的数据,根本没法获取同parent_id下其他文档的name值。要实现需求,我们需要先拿到每个parent_id对应的所有name集合,再把这个集合关联回每个原始文档,最后通过$cond判断$check的值来设置item字段。
方法一:使用$setWindowFields(推荐,MongoDB 5.0+)
这种方法最简洁,不需要额外的分组和关联操作,直接通过窗口函数在每个文档中获取同parent_id的所有name:
const check = false; // 定义你的$check变量 db.getCollection('test').aggregate([ // 为每个文档添加同parent_id的所有name数组 { "$setWindowFields": { "partitionBy": "$parent_id", "output": { "parent_names": { "$addToSet": "$name", "window": { "documents": "unbounded preceding", "documents": "unbounded following" } } } } }, // 根据check的值设置item字段 { "$addFields": { "item": { "$cond": [ check, "YES", "$parent_names" // 这里就是你要的ANSWER部分对应的逻辑 ] } } } ])
方法二:兼容旧版本MongoDB(分组+关联)
如果你的MongoDB版本低于5.0,没法用窗口函数,可以先按parent_id分组收集name数组,再通过$lookup关联回原始文档:
const check = false; db.getCollection('test').aggregate([ // 分组得到每个parent_id对应的name数组 { "$group": { "_id": "$parent_id", "names": { "$addToSet": "$name" } } }, // 关联回原始文档,把names数组带回去 { "$lookup": { "from": "test", "localField": "_id", "foreignField": "parent_id", "as": "docs" } }, // 展开文档,恢复原始结构 { "$unwind": "$docs" }, // 设置item字段 { "$addFields": { "item": { "$cond": [ check, "YES", "$names" // 这里是ANSWER部分对应的内容 ] }, "_id": "$docs._id", "parent_id": "$docs.parent_id", "name": "$docs.name" } }, // 清理不需要的字段 { "$project": { "docs": 0 } } ])
适配你原始的聚合结构
如果你坚持要在你给出的$group结构里实现(虽然这种方式没必要,因为每个_id唯一),那你需要先通过$lookup提前获取同parent_id的name数组,再在$group里使用:
const check = false; db.getCollection('test').aggregate([ // 先关联获取同parent_id的name数组 { "$lookup": { "from": "test", "localField": "parent_id", "foreignField": "parent_id", "as": "parent_docs" } }, // 提取name数组 { "$addFields": { "parent_names": { "$map": { "input": "$parent_docs", "as": "d", "in": "$$d.name" } } } }, // 按_id分组(每个组仅单个文档) { "$group": { "_id": "$_id", "parent_id": { "$last": "$parent_id" }, "name": { "$last": "$name" }, "item": { "$last": { "$cond": [ check, "YES", "$parent_names" // 这就是你要填的ANSWER部分 ] } } } } ])
总结一下,你要的ANSWER部分的正确写法是"$parent_names"(前提是你已经通过窗口函数或关联操作得到了这个同parent_id的name数组)。
内容的提问来源于stack exchange,提问作者tnp.t
相关产品推荐
相关产品推荐

