我想查看集合中是否有一些重复的文档,以便我可以删除或合并类似的记录。
假设没有提供目标值,只提供目标字段,我所要做的就是根据目标字段找到所有类似的文档。
例如,我的集合persons
包含以下文档:
{
_id: 1,
email: "foo@bar.com",
name: "tom",
phone: 320513218,
company: {
name: "Bar"
department: "Marketing"
}
},{
_id: 2,
email: "foo@bar.com",
name: "alex c",
phone: 7320320813,
company: {
name: "Bar"
department: "Development"
}
},{
_id: 3,
email: "not_foo@not_bar.com",
name: "alex w",
phone: 895120981,
company: {
name: "Not Bar"
department: "Development"
}
},{
_id: 4,
email: "not_foo@not_bar.com",
name: "emily",
phone: 895120981,
company: {
name: "Another Company"
department: "Marketing"
}
},{
_id: 5,
email: "foo@bar.com",
name: "emily",
phone: 7320320813,
company: {
name: "Another Company"
department: "Marketing"
}
},...
我想首先找到基于email
的重复文档,我应该得到[{_id: 1, count: 3}, {_id: 2, count: 3}, {_id: 5, count: 3}, {_id: 3, count: 2}, {_id: 4, count: 2}]
作为结果。 (不要担心数组的顺序)
然后,我想找到基于phone
的重复文档,我应该得到[{_id: 2, count: 2}, {_id: 5, count: 2}, {_id: 3, count: 2}, {_id: 4, count: 2}]
作为结果。 (不要担心数组的顺序)
然后,我想找到基于name
的重复文件,我应该得到[{_id: 2, count: 2}, {_id: 3, count: 2}, {_id: 4, count: 2}, {_id: 5, count: 2}]
作为结果。
最后,我想找到基于email
和phone
的重复文档,我应该得到[{_id: 2, count: 2}, {_id: 5, count: 2}]
作为结果。
(count
应该是重复记录的数量(包括在内))
我尝试过mongo / mongoose提供的mapReduce
和aggregate
方法,但它们无法满足我的期望。
我想要的是“按多个(相似)字段分组和计数”
如果您需要更多信息,请告诉我,例如我目前的示例代码。
答案 0 :(得分:1)
每次重复搜索都需要单独的聚合。在所有情况下,只需分组定义重复的(可能是复合的)键,然后将_id
推送到数组并计算结果数:
db.test.aggregate([
{ "$group" : { "_id" : KEY, "ids" : { "$push" : "$_id" }, "count" : { "$sum" : 1 } } }
])
例如,对于phone
:
db.test.aggregate([
{ "$group" : { "_id" : "$phone", "ids" : { "$push" : "$_id" }, "count" : { "$sum" : 1 } } }
])
email
和phone
:
db.test.aggregate([
{ "$group" : { "_id" : { "phone" : "$phone", "email" : "$email" }, "ids" : { "$push" : "$_id" }, "count" : { "$sum" : 1 } } }
])
这会使输出与您请求的输出不同,例如您的示例文档和phone
{ "_id" : 895120981, "ids" : [3, 4], "count" : 2 },
{ "_id" : 7320320813, "ids" : [2, 5], "count" : 2 },
{ "_id" : 320513218, "ids" : [1], "count" : 1 }
但是它有相同的信息,并且是一种更简单(更快)的聚合。
要过滤掉唯一值,请附加$match
阶段:
{ "$match" : { "count" : { "$gt" : 1 } } }
答案 1 :(得分:0)
问题1的解决方案。
db.test.aggregate(
{ $group:
{ _id :
{email : '$email'},
id : {$push :"$_id"},
count : {$sum:1}
}
},
{$unwind:"$id"},
{$group:
{_id:
{_id:"$id",count:"$count"},
}
}
)