为何查询参演至少5部电影的演员时两个MongoDB聚合查询结果不同?
两个MongoDB聚合查询结果差异的原因
问题背景
想要获取参演至少5部电影的演员列表,分别用了两个聚合查询,结果却完全不同:
查询1(使用$unwind)
代码:
db.films.aggregate([ { $unwind:'$actors' }, { $group: { _id: { prenom:'$actors.first_name', nom:'$actors.last_name' }, nbr_films: { $sum: 1 } } }, { $match: { nbr_films:{$gte:5} } }, { $project: { _id:0, nom:"$_id.nom", nbr_films:1 } } ]);
返回结果:
[ { "nbr_films": 6, "nom": "Willis" }, { "nbr_films": 5, "nom": "Oldman" }, { "nbr_films": 6, "nom": "De Niro" }, { "nbr_films": 5, "nom": "Caine" }, { "nbr_films": 6, "nom": "Freeman" } ]
查询2(未使用$unwind)
代码:
db.films.aggregate([ { $group: { _id: { prenom:'$actors.first_name', nom:'$actors.last_name' }, nbr_films: { $sum: 1 } } }, { $match: { nbr_films:{$gte:5} } }, { $project: { _id:0, nom:"$_id.nom", nbr_films:1 } } ]);
返回结果:
[ { "nbr_films": 5 } ]
差异原因
核心问题出在**$group阶段处理数组字段的逻辑**上:
查询1的正确逻辑
$unwind:'$actors'会把每一部包含演员数组的电影文档,拆分成多个独立文档——数组里有多少个演员,就拆成多少条,每条只保留一个演员。- 后续的
$group按单个演员的姓名分组,每一条拆分后的文档对应一部该演员参演的电影,$sum:1就能准确统计出每个演员的参演电影总数。 - 最后通过
$match筛选出参演数≥5的演员,得到符合需求的结果。
查询2的错误逻辑
- 跳过
$unwind直接执行$group时,_id里的$actors.first_name和$actors.last_name是直接引用整个演员数组字段,MongoDB会把完整的演员数组作为分组依据,而非单个演员。 - 此时
$sum:1统计的是拥有完全相同演员名单的电影数量,你得到的nbr_films:5,实际是数据库里有5部电影的演员阵容完全一致,这和你要统计单个演员参演数的需求完全不符。
- 跳过
简单总结:不拆分数组就分组,相当于按「整份演员名单」统计重复电影数,而非按「单个演员」统计参演电影数,逻辑完全跑偏了。
内容的提问来源于stack exchange,提问作者Salah Benkhanous
相关产品推荐
相关产品推荐

