【问题标题】:Fast way to find duplicates on indexed column in mongodb在 mongodb 中的索引列上查找重复项的快速方法
【发布时间】:2010-11-19 12:05:06
【问题描述】:

我在 mongodb 中有一个 md5 集合。我想找到所有重复项。 md5 列已编入索引。您知道使用 map reduce 的任何快速方法吗? 还是应该只遍历所有记录并手动检查重复项?

我目前使用 map reduce 的方法几乎两次迭代集合(假设有非常少量的重复项):

res = db.files.mapReduce(
    function () {
        emit(this.md5, 1);
    }, 
    function (key, vals) {
        return Array.sum(vals);
    }
)

db[res.result].find({value: {$gte:1}}).forEach(
function (obj) {
    out.duplicates.insert(obj)
});

【问题讨论】:

  • OP,请考虑将接受的答案更改为 @expert 的。更简洁更高效

标签: mongodb mapreduce


【解决方案1】:

我个人发现,在大型数据库(1TB 或更多)上,接受的答案非常慢。聚合要快得多。示例如下:

db.places.aggregate(
    { $group : {_id : "$extra_info.id", total : { $sum : 1 } } },
    { $match : { total : { $gte : 2 } } },
    { $sort : {total : -1} },
    { $limit : 5 }
    );

它搜索 extra_info.id 被使用两次或多次的文档,按给定字段的降序对结果进行排序并打印它的前 5 个值。

【讨论】:

  • 我不太明白您的解决方案如何处理问题数据。组行应该是{ $group : {'md5' : "$extra_info.md5", total : { $sum : 1}}},吗?
  • @zhon 没有。你读过文档吗?它说For this _id field, you can specify various expressions, including a single field from the documents in the pipeline, a computed value from a previous stage, a document that consists of multiple fields, and other valid expressions, such as constant or subdocument fields. You can use $project operators in expressions for the _id field.
  • 对于问题数据,分组行应该是: { $group : { _id : "$md5", total : { $sum : 1 } } },
【解决方案2】:

一次性完成最简单的方法是按 md5 排序,然后进行适当的处​​理。

类似:

var previous_md5;
db.files.find( {"md5" : {$exists:true} }, {"md5" : 1} ).sort( { "md5" : 1} ).forEach( function(current) {

  if(current.md5 == previous_md5){
    db.duplicates.update( {"_id" : current.md5}, { "$inc" : {count:1} }, true);
  }

  previous_md5 = current.md5;

});

那个小脚本对 md5 条目进行排序并按顺序循环它们。如果一个 md5 被重复,那么它们将在排序后“背靠背”。所以我们只保留一个指向previous_md5 的指针并比较它current.md5。如果我们找到重复项,我会将其放入 duplicates 集合中(并使用 $inc 来计算重复项的数量)。

此脚本意味着您只需遍历一次主数据集。然后你可以循环遍历duplicates 集合并执行清理。

【讨论】:

    【解决方案3】:

    您可以按该字段进行分组,然后查询以获取重复项(计数 > 1)。 http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group

    虽然,最快的方法可能是只执行一个只返回该字段的查询,然后在客户端进行聚合。 Group/Map-Reduce 需要提供对整个文档的访问,这比仅提供来自索引的数据(现在在 1.7.3+ 中涵盖)要昂贵得多。

    如果这是您需要定期运行的一般问题,您可能希望保留一个只有 {md5:value, count:value} 的集合,这样您就可以跳过聚合,并且在您需要时它会非常快剔除重复项。

    【讨论】:

    • 我不能使用 gruping,因为它仅限于 10k 个元素(我有 3M)。但是 MR 将只返回索引中的数据这一点很有趣。我不知道。谢谢! (+1)
    猜你喜欢
    • 2019-05-28
    • 2016-01-14
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2020-07-24
    • 2013-07-22
    相关资源
    最近更新 更多