mongo 3在唯一索引上重复 - dropDups

Alo*_*orz 16 indexing unique duplicate-removal mongodb

在mongoDB的文档中,它说:"在版本3.0中更改:dropDups选项不再可用."

如果我真的想创建一个唯一的索引并销毁重复的条目,我还能做什么(除了降级)?

请记住,我每秒收到大约300个插入,所以我不能删除所有重复项,并希望在我完成索引编制时不会有任何内容.

Max*_*net 13

是的dropDupes,现在被弃用,因为2.7.5版本,因为它不能够正确地预测哪些文件会在这个过程中被删除.

通常,您有两个选择:

  1. 使用新的集合:

    • 创建一个新的集合,
    • 在这个新集合上创建唯一索引,
    • 运行批处理将旧集合中的所有文档复制到新集合,并确保在此过程中忽略重复的密钥错误.
  2. 手动处理您自己的集合中的它:

    • 确保您不会在代码中插入更多重复的文档,
    • 在您的集合上运行批处理以删除重复项(如果它们不完全相同,请确保保留好的副本),
    • 然后添加唯一索引.

对于你的特殊情况,我会建议第一个选项,但有一个技巧:

  • 创建具有唯一索引的新集合,
  • 更新您的代码,以便您现在在两个表中插入文档,
  • 运行批处理将所有文档从旧集合复制到新集合(忽略重复密钥错误),
  • 重命名新集合以匹配旧名称.
  • 重新更新您的代码,以便您现在只在"旧"集合中编写


Ale*_*lex 8

正如@ Maxime-Beugnet所强调的那样,您可以创建批处理脚本以从集合中删除重复项.如果重复数量与集合大小相比较小,那么下面我的方法包含了相对较快的方法.出于演示目的,此脚本将重复删除由以下脚本创建的集合:

db.numbers.drop()

var counter = 0
while (counter<=100000){
  db.numbers.save({"value":counter})
  db.numbers.save({"value":counter})
  if (counter % 2 ==0){
    db.numbers.save({"value":counter})
  }
  counter = counter + 1;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过编写返回具有多个重复项的所有记录的聚合查询来删除此集合中的重复项.

var cur = db.numbers.aggregate([{ $group: { _id: { value: "$value" }, uniqueIds: { $addToSet: "$_id" }, count: { $sum: 1 } } }, { $match: { count: { $gt: 1 } } }]);
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用游标迭代重复的记录并实现自己的业务逻辑,以决定要删除哪些重复项.在下面的例子中,我只是保持第一次出现:

while (cur.hasNext()) {
    var doc = cur.next();
    var index = 1;
    while (index < doc.uniqueIds.length) {
        db.numbers.remove(doc.uniqueIds[index]);
        index = index + 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

删除重复项后,您可以添加唯一索引:

db.numbers.createIndex( {"value":1},{unique:true})
Run Code Online (Sandbox Code Playgroud)