2011-04-03 81 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 
});