【问题标题】:MongoDB Finding duplicates sharing multiple fields using MapReduceMongoDB 使用 MapReduce 查找共享多个字段的重复项
【发布时间】:2014-11-26 16:18:28
【问题描述】:

我正在尝试在用于生产的 Mongo 2.4 版数据库中查找重复项,因此无法更新。由于 2.4 中不存在聚合,我无法使用聚合管道 来查找重复项,因此我正在尝试使用 MapReduce 找到解决方案。

我已经通过 MongoVUE 的 Map Reduce 接口尝试了以下一组 map、reduce 和 finalize 函数,它们在 3,000,000 条记录集合上运行不到一秒后没有返回任何内容,这些记录集合在指定的字段上肯定有重复项。显然出了点问题,但 MongoVUE 没有显示任何错误消息或有用的指示。

function Map() {
  emit(
    {name: this.name, LocationId: this.LocationId, 
     version: this.version},
    {count:1, ScrapeDate: this.ScrapeDate}
  );
}

function Reduce(key, values) {
  var reduced = {count:0, ScrapeDate:''2000-01-01''};
  values.forEach(function(val) {
    reduced.count      += val.count;
    if (reduced.ScrapeDate.localeCompare(val.ScrapeDate) < 0)
      reduced.ScrapeDate=val.ScrapeDate;
  });

  return reduced;
  return values[0];
}

function Finalize(key, reduced) {
  if (reduced.count > 1)
    return reduced;
}

我只需要找到共享相同nameLocationIdversion 的多条记录的任何实例,并理想地显示此类记录的最新ScrapeDate

【问题讨论】:

    标签: javascript mongodb mapreduce duplicates


    【解决方案1】:

    您的 map-reduce 代码没有任何问题,但对于一个非常小的数据集。我认为reduce函数中的return values[0];会是复制粘贴错误。您可以通过 mongo shell 尝试相同的操作。

    由于 2.4 中不存在聚合,我无法使用聚合管道查找重复项,因此我正在尝试寻找解决方案 使用 MapReduce。

    你错了,db.collection.aggregate(pipeline, options)是在version 2.2中引入的。

    这是使用 aggregation 框架的方法,但由于您的数据集非常庞大,并且在 v2.4 中 $sort 运算符的内存限制为 RAM 的 10%,因此它不是首选。

    db.collection.aggregate(
     [
       // sort the records, based on the 'ScrapeDate' field, in descending order.
       {$sort:{"ScrapeDate":-1}},
    
       // group by the key fields, and take the 'ScrapeDate' of the first document,
       // Since it is in sorted order, the first document would contain the  
       // highest field value.
       {$group:{"_id":{"name":"$name","LocationId":"$LocationId","version":"$version"}
                ,"ScrapeDate":{$first:"$ScrapeDate"}
                ,"count":{$sum:1}}
               },
    
       // output only the group, having documents greater than 1.
       {$match:{"count":{$gt:1}}}
    ]
    );
    

    来到您的 Map-reduce 函数,它在我的测试数据上运行没有问题。

    db.collection.insert({"name":"c","LocationId":1,"version":1,"ScrapeDate":"2000-01-01"});
    db.collection.insert({"name":"c","LocationId":1,"version":1,"ScrapeDate":"2001-01-01"});
    db.collection.insert({"name":"c","LocationId":1,"version":1,"ScrapeDate":"2002-01-01"});
    db.collection.insert({"name":"d","LocationId":1,"version":1,"ScrapeDate":"2002-01-01"});
    

    运行 map-reduce,

    db.collection.mapReduce(Map,Reduce,{out:{"inline":1},finalize:Finalize});
    

    o/p:

    {
            "results" : [
                    {
                            "_id" : {
                                    "name" : "c",
                                    "LocationId" : 1,
                                    "version" : 1
                            },
                            "value" : {
                                    "count" : 3,
                                    "ScrapeDate" : "2002-01-01"
                            }
                    },
                    {
                            "_id" : {
                                    "name" : "d",
                                    "LocationId" : 1,
                                    "version" : 1
                            },
                            "value" : null
                    }
            ],
            "timeMillis" : 0,
            "counts" : {
                    "input" : 4,
                    "emit" : 4,
                    "reduce" : 1,
                    "output" : 2
            },
            "ok" : 1,
    }
    

    请注意,输出包含 value:null 用于没有任何重复的记录。

    这是由于您的finalize 功能:

    function Finalize(key, reduced) {
      if (reduced.count > 1)
        return reduced; // returned null by default for keys with single value,
                        // i.e count=1
    }
    

    finalize 函数过滤掉键。所以你不能只得到重复的键。您将在 map-reduce 输出中获得所有键。在您的 finalize 函数中,您可以不显示它们的值,这就是您正在做的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 2013-05-30
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多