如何在MongoDB聚合管道中实现两查询结果的ID交集?
实现与SQL内联查询等价的MongoDB聚合管道
我需要创建一个MongoDB聚合管道,实现和以下SQL查询相同的功能:
SELECT DISTINCT A.ID FROM (Query_A) A INNER JOIN (Query_B) B ON A.ID = B.ID
我已经写好了用$facet运行两个子查询的初始代码:
[ { "$facet": { "query_a": [...], // 这里是Query_A的聚合逻辑 "query_b": [...] // 这里是Query_B的聚合逻辑 } }, ... // 需要补充后续步骤获取ID交集 ]
补充说明
$facet步骤执行后的结果如下:
[ { "queryA": [ {"ID": "c80ea2cb-3272-77ae-8f46-d95de600c5bf", "date": "1"}, {"ID": "cdbcc129-548a-9d51-895a-1538200664e6", "date": "2"}, {"ID": "a4ece1ba-42ae-e735-17b0-f619daa506f9", "date": "3"} ], "queryB": [ {"ID": "c80ea2cb-3272-77ae-8f46-d95de600c5bg", "date": "4"}, {"ID": "cdbcc129-548a-9d51-895a-1538200664e6", "date": "5"}, {"ID": "a4ece1ba-42ae-e735-17b0-f619daa506f9", "date": "6"} ] } ]
我期望得到的最终结果是:
[ { "dateA": "2", "dateB": "5", "intersection": "cdbcc129-548a-9d51-895a-1538200664e6" }, { "dateA": "3", "dateB": "6", "intersection": "a4ece1ba-42ae-e735-17b0-f619daa506f9" } ]
解决方案
在$facet之后添加以下聚合阶段即可实现需求:
[ { "$facet": { "queryA": [...], // 原有Query_A逻辑 "queryB": [...] // 原有Query_B逻辑 } }, // 拆分queryA数组为单个文档,同时保留queryB数组 { "$unwind": "$queryA" }, // 拆分queryB数组为单个文档,让两个子查询的文档两两匹配 { "$unwind": "$queryB" }, // 筛选ID相等的匹配项 { "$match": { "$expr": { "$eq": ["$queryA.ID", "$queryB.ID"] } } }, // 重构输出文档结构,提取目标字段 { "$project": { "_id": 0, "dateA": "$queryA.date", "dateB": "$queryB.date", "intersection": "$queryA.ID" } }, // 按ID分组去重,避免重复结果 { "$group": { "_id": "$intersection", "dateA": { "$first": "$dateA" }, "dateB": { "$first": "$dateB" } } }, // 再次调整结构,移除自动生成的_id字段 { "$project": { "_id": 0, "dateA": 1, "dateB": 1, "intersection": "$_id" } } ]
步骤说明
$unwind:两次拆分数组,让两个子查询的结果文档能两两组合匹配。$match:通过$expr比较字段值,仅保留ID相同的匹配对。$project:调整输出字段名称和结构,对齐期望格式。$group:确保每个ID仅出现一次,避免子查询存在重复ID时导致结果冗余。
内容的提问来源于stack exchange,提问作者Jord
相关产品推荐
相关产品推荐

