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

时间:2015-05-12 10:07:53

标签: mongodb indexing unique duplicate-removal

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

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

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

3 个答案:

答案 0 :(得分:12)

从版本2.7.5起,是dropDupes现在是deprecated,因为无法正确预测在此过程中将删除哪个文档。

通常,您有两个选项:

  1. 使用新系列:

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

    • 确保您不会在代码中插入更多重复的文档,
    • 在您的收藏集上运行批处理以删除重复项(如果它们不完全相同,请确保保留好的),
    • 然后添加唯一索引。
  3. 对于您的具体情况,我建议第一个选项,但有一个技巧:

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

答案 1 :(得分:7)

正如@ 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;
}

您可以通过编写一个返回所有包含多个副本的记录的聚合查询来删除此集合中的重复项。

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

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

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

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

db.numbers.createIndex( {"value":1},{unique:true})

答案 2 :(得分:0)

pip install mongo_remove_duplicate_indexes

最好的方法是创建一个python脚本或者你喜欢的任何语言,迭代集合,使用 db.collectionname.createIndex({&#39; indexname&#)创建一个唯一索引设置为true的新集合39;:1},unique:true),并将您之前集合中的文档插入到新集合中,因为您想要删除的密钥或删除的重复项不会插入到您的新集合中,并且您可以处理ecxeption容易处理异常

查看示例

的包源代码