如何用PyMongo聚合查询嵌入匹配的Episodes与Sequences文档
实现嵌套关联的MongoDB聚合管道方案
当然可以在单个聚合管道里完成这个需求!你当前的查询已经迈出了第一步——关联Episodes集合,但要实现嵌套的Sequences关联,需要用到$lookup的子管道功能(结合let和pipeline参数),这样就能针对每个Episode单独匹配对应的Sequences了。
完整的聚合管道代码(PyMongo版本)
from pymongo import MongoClient # 连接数据库(根据你的实际配置调整) client = MongoClient("mongodb://localhost:27017/") db = client.your_db_name # 替换成你的数据库名 # 定义聚合管道 pipeline = [ # 第一步:筛选目标项目A,减少后续处理的数据量 {"$match": {"_id": "A"}}, # 第二步:关联Episodes集合,获取该项目下的所有剧集 {"$lookup": { "from": "episodes", "localField": "_id", "foreignField": "project", "as": "episodes" }}, # 第三步:拆分episodes数组,让每个剧集成为独立文档,方便后续单独处理 {"$unwind": "$episodes"}, # 第四步:针对每个剧集,嵌套关联对应的Sequences集合 {"$lookup": { "from": "sequences", # 定义变量,传递当前项目ID和剧集名称到子管道 "let": { "current_project": "$_id", "current_episode_name": "$episodes.name" }, # 子管道:匹配当前项目下、对应剧集的序列 "pipeline": [ {"$match": { "$expr": { "$and": [ {"$eq": ["$project", "$$current_project"]}, {"$eq": ["$episode", "$$current_episode_name"]} ] } }} ], # 将匹配到的序列存入当前剧集的sequences字段 "as": "episodes.sequences" }}, # 第五步:重新按项目ID分组,把处理后的剧集重新组合成数组 {"$group": { "_id": "$_id", "episodes": {"$push": "$episodes"} }} ] # 执行聚合查询并输出结果 result = list(db.projects.aggregate(pipeline)) print(result)
关键步骤解释
$match筛选项目:先定位到Project A,避免处理无关数据,提升查询效率。- 第一层
$lookup关联Episodes:这部分和你原来的逻辑一致,把项目对应的所有剧集存入episodes数组。 $unwind拆分数组:因为我们需要对每个剧集单独关联Sequences,所以必须把数组拆成单个文档处理。- 嵌套
$lookup关联Sequences:- 用
let定义两个变量:当前项目的ID和当前剧集的名称(对应Sequences集合里的episode字段)。 - 子管道里用
$expr结合变量匹配条件,确保只获取当前项目、当前剧集下的序列。 - 把匹配结果直接存入当前剧集对象的
sequences字段,实现嵌套结构。
- 用
$group重组数组:把拆分后的单个剧集文档重新按项目ID分组,还原成包含嵌套剧集和序列的结构。
结果说明
执行这个管道后,你会得到完全符合预期格式的结果:
[ { "_id": "A", "episodes": [ { "_id": "A/Episode01", "project": "A", "name": "Episode01", "sequences": [ { "_id": "A/Episode01/Sequence01", "project": "A", "episode": "Episode01", "name": "Sequence01" } ] }, { "_id": "A/Episode02", "project": "A", "name": "Episode02", "sequences": [ { "_id": "A/Episode02/Sequence02", "project": "A", "episode": "Episode02", "name": "Sequence02" } ] } ] } ]
另外,你原来查询里的$group是多余的——因为$match已经只返回一个Project文档,没必要再分组,反而会增加不必要的复杂度。
内容的提问来源于stack exchange,提问作者Green Cell
相关产品推荐
相关产品推荐

