【问题标题】:MongoDB drop duplicates with ensureIndex but keep the last entry not the firstMongoDB 使用 ensureIndex 删除重复项,但保留最后一个条目而不是第一个条目
【发布时间】:2015-02-18 11:17:35
【问题描述】:

我有一个重复的问题。

我正在尝试从 MongoDB 集合中删除所有重复项,问题是我不想保留第一个条目而是最后一个。

这是我保留第一个条目的方式:

db.CUDB.ensureIndex( { CUid: 1 }, { unique: true, dropDups: true } )

但我希望能够以相反的方式 insureIndex 并保留最后添加的条目而不是第一个。

最简单的方法是什么?

【问题讨论】:

    标签: mongodb duplicates


    【解决方案1】:

    ensureIndex 不提供执行此操作的方法。它也没有告诉哪些值将被删除。

    在您的情况下,我会尝试执行以下操作(肯定会比确保索引更慢)。 我还假设您有一些字段(在我的情况下为 created_at),这取决于您决定一个文档是否比另一个文档更旧):

    var checked = {}; // basically a hash, which ensures O(1) lookup
    db.coll.find().sort({created_at: -1}).forEach(function(o){
      if (o['CUid'] in checked){
        db.coll.remove({_id: o['_id']});
      } else {
        checked[o['CUid']] = 1;
      }
    })
    

    所以基本上我们以相反的顺序(最新的第一个)迭代您的所有文档,并检查我们是否已经看到您的CUid 字段。如果我们没有,则保留此文档原样并将其标记为已查看。如果稍后我们看到任何其他具有相同 CUid 的文档,我们可以将其删除。

    您最终将对您的集合进行一次完整扫描,并为每个重复的元素进行N 额外的数据库调用。

    反向排序将确保保存最新的元素。

    附言

    注意上述代码中的错误;我只是证明了它是正确的,不是 试过了。

    然后告诉我进展如何。

    P.P.S.如果您仍然无法对 mongo 中的所有集合进行排序,我会尝试在应用层执行此操作。基本上你会找到你所有的集合,用你想要的任何语言对它们进行排序,然后在那里也执行相同的逻辑。

    【讨论】:

    • 这看起来很棒,但我有一个小内存问题:Runner error: Overflow sort stage buffered data usage of 33578371 bytes exceeds internal limit of 33554432 bytes 另外,数据库有大约 300k 条目,大约 1.6GB :-s
    • @Eek 这是一个大问题:-)。这意味着没有足够的内存来对所有集合进行排序。可能有帮助的是在created_at 的模拟上创建一个索引,因为没有索引你不能使用超过 64MB(令我惊讶的是,在你的情况下它在 32MB 后关闭)
    猜你喜欢
    • 1970-01-01
    • 2016-02-14
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多