MongoDB 使用 ensureIndex 删除重复项,但保留最后一个条目而不是第一个条目
Posted
技术标签:
【中文标题】MongoDB 使用 ensureIndex 删除重复项,但保留最后一个条目而不是第一个条目【英文标题】:MongoDB drop duplicates with ensureIndex but keep the last entry not the first 【发布时间】:2015-02-18 11:17:35 【问题描述】:我有一个重复的问题。
我正在尝试从 MongoDB 集合中删除所有重复项,问题是我不想保留第一个条目而是最后一个。
这是我保留第一个条目的方式:
db.CUDB.ensureIndex( CUid: 1 , unique: true, dropDups: true )
但我希望能够以相反的方式 insureIndex 并保留最后添加的条目而不是第一个。
最简单的方法是什么?
【问题讨论】:
【参考方案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 后关闭)以上是关于MongoDB 使用 ensureIndex 删除重复项,但保留最后一个条目而不是第一个条目的主要内容,如果未能解决你的问题,请参考以下文章