删除MongoDB中的重复项

时间:2016-02-29 19:04:41

标签: mongodb mongodb-query

我有一个名为" contact_id"的字段的集合。 在我的收藏中,我有这个密钥的重复寄存器。

如何删除重复项,导致只有一个注册表?

我已经尝试过:

db.PersonDuplicate.ensureIndex({"contact_id": 1}, {unique: true, dropDups: true}) 

但是没有用,因为函数dropDups在MongoDB 3.x中不再可用

我使用3.2

由于

5 个答案:

答案 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)

我使用了这种方法:

  1. 获取特定集合的mongo转储。
  2. 清除该收藏集
  3. 添加唯一的键索引
  4. 使用mongorestore恢复转储。

答案 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可以方便地替换指定集合的​​内容,从而使该解决方案成为可能。