【问题标题】:mongo 3 duplicates on unique index - dropDupsmongo 3在唯一索引上重复 - dropDups
【发布时间】:2015-07-23 03:20:17
【问题描述】:

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

如果我真的想创建唯一索引并销毁重复条目,我可以做些什么(降级除外)?

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

【问题讨论】:

  • 我不明白你的问题。我是否正确地知道您有现有的文档,包括骗子,现在您想在联系重复的字段上放置一个唯一索引,同时潜在的新骗子进来?
  • 是的。我想摆脱 dups,如果新的进来拒绝他们。
  • 我也遇到了这个问题,有没有其他方法可以在没有dropDups in MongoDB >= 3.* 的情况下消除重复项??

标签: mongodb indexing unique duplicate-removal


【解决方案1】:

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

通常,您有 2 个选项:

  1. 使用新的集合:

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

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

对于您的特殊情况,我会推荐 第一个选项,但有一个技巧:

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

【讨论】:

  • 选项 1 可能也是重建索引的最佳方式,因为实时系统必须等待重建索引,这会减慢速度。
  • make sure you ignore duplicated key error during the process. 你会怎么做?似乎错误停止了交易中途
  • 使用 MongoDB 无序批量插入:“如果在处理其中一个写操作的过程中发生错误,MongoDB 将继续处理列表中剩余的写操作。”示例:db.persons.insert([{"_id" : "Bob"}, {"_id" : "John"}, {"_id" : "Bob"}, {"_id" : "Marc"}], {ordered : false }) 将插入 3 个文档并显示一个重复键错误。使用 {ordered : true},只会插入前 2 个。更多文档here
  • @Quest :记住 MongoDB 中没有事务:它不是 ACID。如果你运行 10 次插入,如果第五次返回错误,它不会回滚。不要将此与文档级别锁定误认为是一种“迷你”事务,仅适用于一个文档。
  • DropDups 已从 2.6 版本的 MongoDB 中弃用。 docs.mongodb.com/v2.6/tutorial/create-a-unique-index/…
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    pip install mongo_remove_duplicate_indexes

    最好的方法是创建一个 python 脚本或任何你喜欢的语言,迭代集合,创建一个唯一索引设置为 true 的新集合 db.collectionname.createIndex({'indexname':1} ,unique:true),并将您的文档从以前的集合插入到新集合中,因为您想要区分的键或删除的重复项不会插入到您的新集合中,您可以通过异常处理轻松处理异常

    查看示例的包源代码

    【讨论】:

      猜你喜欢
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      • 2016-02-17
      • 1970-01-01
      • 2013-04-13
      相关资源
      最近更新 更多