MongoDB聚合查询取最早重复文献返回Null,求排查错误原因
MongoDB聚合查询错误分析:筛选同一作者下最早发表的重复标题文献
问题描述
我拥有名为article_titles的MongoDB集合,其中存在重复的文献标题,需求是筛选出同一作者下最早发表的文献。集合数据如下:
{ "_id" : ObjectId("6375dbf89a70ce15b7c51172"), "title" : "Visualizing Graphs and Clusters as Maps", "year" : 2005, "name" : "amir" } { "_id" : ObjectId("6375dbf89a70ce15b7c5118a"), "title" : "Visualizing Dynamic Data with Maps", "year" : 2012, "name" : "amir" } { "_id" : ObjectId("6375dbf89a70ce15b7c511ac"), "title" : "Visualizing Cartograms: Goals and Task Taxonomy", "year" : 2015, "name" : "kobourov" } { "_id" : ObjectId("6375dbf99a70ce15b7c60293"), "title" : "Upward straight-line embeddings of directed graphs into point sets", "year" : 2008, "name" : "hossain" } { "_id" : ObjectId("6375dbf99a70ce15b7c738c7"), "title" : "Upward straight-line embeddings of directed graphs into point sets", "year" : 2010, "name" : "hossain" }
其中作者hossain有两篇同标题、不同发表年份的文献,我尝试使用以下聚合查询获取最早的那篇:
db.article_titles.aggregate([{$sort:{year:-1}},{$group:{_id:{title:"$title",name:"$name",year:{$first:"$year"}}}}])
但该查询返回Null值,想了解我的操作哪里存在错误?
错误原因
- 排序方向错误:你用
{$sort:{year:-1}}按年份降序排列,此时$first会取到每组中最新年份的记录,而你需要的是最早发表的,应该改为升序排序{$sort:{year:1}}。 - 分组依据错误:你将
year:{$first:"$year"}包含在_id字段中,_id是分组的唯一标识,这会导致每条记录因年份不同而单独成组,根本无法聚合同一作者同一标题的重复记录,最终返回的结果不符合预期。
正确的聚合查询
方法一:先排序再分组取第一条
通过升序排序确保每组第一条是最早的记录,再按作者和标题分组提取:
db.article_titles.aggregate([ // 按年份升序排列,让最早的记录排在每组最前面 {$sort: {year: 1}}, // 按作者和标题分组,取每组的第一条完整记录 {$group: { _id: {title: "$title", name: "$name"}, earliestArticle: {$first: "$$ROOT"} }}, // 将结果替换为完整的文献记录,方便查看 {$replaceRoot: {newRoot: "$earliestArticle"}} ])
方法二:先分组找最小年份再关联原数据
先统计每个作者每个标题的最早年份,再匹配原集合获取完整记录:
db.article_titles.aggregate([ // 分组获取每个作者每个标题的最小发表年份 {$group: { _id: {title: "$title", name: "$name"}, minYear: {$min: "$year"} }}, // 关联原集合,匹配对应作者、标题和年份的记录 {$lookup: { from: "article_titles", localField: ["_id.title", "_id.name", "minYear"], foreignField: ["title", "name", "year"], as: "earliestArticle" }}, // 展开关联结果 {$unwind: "$earliestArticle"}, // 替换根节点为完整的文献记录 {$replaceRoot: {newRoot: "$earliestArticle"}} ])
内容的提问来源于stack exchange,提问作者user110920
相关产品推荐
相关产品推荐

