2011-04-03 178 views
7

我正在使用MongoDB并需要删除重复的记录。我有一个上市的收集,看起来像这样:(简体)使用MapReduce删除重复的记录

[ 
    { "MlsId": "12345"" }, 
    { "MlsId": "12345" }, 
    { "MlsId": "23456" }, 
    { "MlsId": "23456" }, 
    { "MlsId": "0" }, 
    { "MlsId": "0" }, 
    { "MlsId": "" }, 
    { "MlsId": "" } 
] 

的列表为重复,如果MlsId不是“”或“0”,另一个上市具有相同的MlsId。所以在上面的例子中,第二个和第四个记录需要被删除。

如何查找所有重复列表并将其删除?我开始研究MapReduce,但找不到适合我的案例。

这里是我到目前为止,但它不检查MlsId为“0”或“”:

m = function() { 
    emit(this.MlsId, 1); 
} 

r = function (k, vals) { 
    return Array.sum(vals); 
} 

res = db.Listing.mapReduce(m,r); 
db[res.result].find({value: {$gt: 1}}); 
db[res.result].drop(); 

回答

2

我没有使用MongoDB的,但我已经使用MapReduce的。我认为你在mapreduce函数方面是正确的。为了排除他0和空字符串,你可以在地图功能本身添加一个检查..像

m = function() { 
    if(this.MlsId!=0 && this.MlsId!="") {  
    emit(this.MlsId, 1); 
    } 
} 

而减少应返回键 - 值对。因此,它应该是:

r = function(k, vals) { 
    emit(k,Arrays.sum(vals); 
} 

在这之后,你应该有一组键值对的输出,使得关键是MlsId和值是这个特殊的ID出现thimes的数量。我不确定db.drop()部分。正如你指出的那样,它很可能会删除所有MlsIds,而不是只删除重复的。为了解决这个问题,也许你可以先调用drop(),然后重新创建一次MlsId。这对你有用吗?

+0

你可能不能够回答这个问题,但如果我宣布M和R的功能,然后执行mapReduce函数,然后运行db [res.result] .drop();命令,它会删除所有列表还是只删除重复的列表?我不明白mapReduce并发出所以不知道这是如何工作的... – Justin 2011-04-03 16:18:56

+0

我已经做了reduce()的小修改。我不知道锄头db.drop()的作品,但是,是的,我想它会删除所有针对该特定Id的委托。但我希望你对map-reduce部分的理解是清楚的。我不确定mongodb的语法,但..会看到我是否可以找出一些东西.. – 2011-04-03 16:51:51

+0

你可以尝试添加一个索引与删除重复选项,这里提到:http://www.mongodb.org/display/DOCS/索引它会自动删除重复值。另一种方法是首先删除()所有值,然后添加一个值。 – 2011-04-03 17:02:47

2

在mongodb中,您可以使用查询来限制传入以进行映射的文档。你可能想为那些你不关心的人做这件事。然后在reduce函数中,您可以忽略dups,并仅为每个重复键返回一个文档。

虽然我对你的目标有点困惑。如果您只想查找重复项并删除其中的一个,那么您只需在该字段上创建一个唯一索引并使用dropDups选项;创建索引的过程将删除重复的文档。保持索引将确保它不会再发生。

http://www.mongodb.org/display/DOCS/Indexes#Indexes-DuplicateValues

+0

如上所述,我不能在dropDups中使用唯一索引,因为它只会保留一个带有值“”的列表和一个列表值为“0”时,我想保留所有这些。 – Justin 2011-04-03 20:02:04

-1

可以使用聚合操作来删除重复。放松一下,引入一个虚拟的$组和$ sum阶段,并忽略下一阶段的计数。事情是这样的,

db.myCollection.aggregate([ 
{ 
    $unwind: '$list' 
}, 
{ 
    $group:{ 
    '_id': 
     { 
     'listing_id':'$_id', 'MlsId':'$list.MlsId' 
     }, 
      'count': 
     { 
      '$sum':1 
     } 
     } 
}, 
{ 
     $group: 
     { 
     '_id':'$_id.listing_id', 
     'list': 
     { 
      '$addToSet': 
      { 
      'MlsId':'$_id.MlsId' 
      } 
     } 
     } 
} 
]); 
-1

这是我继@harri答案删除重复:

//contains duplicated documents id and numeber of duplicates 
db.createCollection("myDupesCollection") 
res = db.sampledDB.mapReduce(m, r, { out : "myDupesCollection" }); 

// iterate through duplicated docs and remove duplicates (keep one) 
db.myDupesCollection.find({value: {$gt: 1}}).forEach(function(myDoc){ 
    u_id = myDoc._id.MlsId; 
    counts =myDoc.value; 
    db.sampledDB.remove({MlsId: u_id},counts-1); //if there are 3 docs, remove 3-1=2 of them 
});