我有一个名为" contact_id"的字段的集合。 在我的收藏中,我有这个密钥的重复寄存器。
如何删除重复项,导致只有一个注册表?
我已经尝试过:
db.PersonDuplicate.ensureIndex({"contact_id": 1}, {unique: true, dropDups: true})
但是没有用,因为函数dropDups在MongoDB 3.x中不再可用
我使用3.2
由于
答案 0 :(得分:23)
是的,dropDups已经不复存在了。但是你可以毫不费力地实现你的目标。
您需要首先找到所有重复的行,然后删除除第一行之外的所有行。
db.dups.aggregate([{$group:{_id:"$contact_id", dups:{$push:"$_id"}, count: {$sum: 1}}},
{$match:{count: {$gt: 1}}}
]).forEach(function(doc){
doc.dups.shift();
db.dups.remove({_id : {$in: doc.dups}});
});
如您所见doc.dups.shift()
将从数组中删除第一个 _id ,然后删除所有包含dups数组中剩余_ids的文档。
脚本将删除所有重复的文档。
答案 1 :(得分:6)
对于mongod 3+来说这是一个很好的模式,这也确保你不会运行我们的内存,这可能发生在真正的大集合中。您可以将其保存到dedup.js文件,对其进行自定义,然后使用以下命令对所需的数据库运行:mongo localhost:27017 / YOURDB dedup.js
var duplicates = [];
db.runCommand(
{aggregate: "YOURCOLLECTION",
pipeline: [
{ $group: { _id: { DUPEFIELD: "$DUPEFIELD"}, dups: { "$addToSet": "$_id" }, count: { "$sum": 1 } }},
{ $match: { count: { "$gt": 1 }}}
],
allowDiskUse: true }
)
.result
.forEach(function(doc) {
doc.dups.shift();
doc.dups.forEach(function(dupId){ duplicates.push(dupId); })
})
printjson(duplicates); //optional print the list of duplicates to be removed
db.YOURCOLLECTION.remove({_id:{$in:duplicates}});
答案 2 :(得分:1)
我使用了这种方法:
答案 3 :(得分:0)
也许是尝试创建tmpColection,创建唯一索引,然后从源复制数据,最后一步是交换名称?
其他想法,我的目的是将索引加倍(使用聚合),然后通过调用remove()方法并将justOne参数设置为true或1来循环。
var itemsToDelete = db.PersonDuplicate.aggregate([
{$group: { _id:"$_id", count:{$sum:1}}},
{$match: {count: {$gt:1}}},
{$group: { _id:1, ids:{$addToSet:"$_id"}}}
])
并通过ids数组进行循环 这对你有意义吗?
答案 4 :(得分:0)
我们还可以使用$out
阶段,通过将每个副本中的内容替换为一个副本来从集合中删除副本。
例如,每个值x
仅保留一个元素:
// > db.collection.find()
// { "x" : "a", "y" : 27 }
// { "x" : "a", "y" : 4 }
// { "x" : "b", "y" : 12 }
db.collection.aggregate(
{ $group: { _id: "$x", onlyOne: { $first: "$$ROOT" } } },
{ $replaceWith: "$onlyOne" }, // prior to 4.2: { $replaceRoot: { newRoot: "$onlyOne" } }
{ $out: "collection" }
)
// > db.collection.find()
// { "x" : "a", "y" : 27 }
// { "x" : "b", "y" : 12 }
此:
$group
的文档,由定义重复项的字段(此处为x
)组成,并通过仅保留一个(找到的$first
)并将其赋予值$$ROOT
,即文档本身。在此阶段结束时,我们将看到以下内容:
{ "_id" : "a", "onlyOne" : { "x" : "a", "y" : 27 } }
{ "_id" : "b", "onlyOne" : { "x" : "b", "y" : 12 } }
$replaceWith
输入文档中所有现有的字段,以及我们在onlyOne
阶段创建的$group
字段的内容,以查找原始格式。在此阶段结束时,我们将看到以下内容:
{ "x" : "a", "y" : 27 }
{ "x" : "b", "y" : 12 }
$replaceWith
仅从Mongo 4.2
开始可用。在以前的版本中,我们可以改用$replaceRoot
:
{ $replaceRoot: { newRoot: "$onlyOne" } }
$out
将聚合管道的结果插入同一集合中。请注意,$out
可以方便地替换指定集合的内容,从而使该解决方案成为可能。