2011-04-03 25 views
7

MongoDB kullanıyorum ve yinelenen kayıtları kaldırmalıyım. MlsId "değil" veya "0" ve başka listeleme aynı MlsId varsa (basitleştirilmiş) Bir giriş, yineleniyorMapReduce kullanarak yinelenen kayıtları kaldırma

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

: Öyle gibi görünen bir liste koleksiyonu var. Yani yukarıdaki örnekte, 2. ve 4. kayıtların kaldırılması gerekecektir.

Tüm yinelenen listeleri nasıl bulabilir ve kaldırabilirim? MapReduce'a bakmaya başladım ama davamıma uyan bir örnek bulamadım. İşte

Ben bugüne kadar ne olduğunu, ancak MlsId "0" veya "" ise o kontrol etmez: Ben mongodb kullanmadıysanız ama mapreduce kullandık

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(); 

cevap

2

. Haritacı fonksiyonlar açısından doğru yolda olduğunuzu düşünüyorum. o 0 ve boş dizeleri hariç tutmak için,

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

gibi .. haritası da kendiliğinden bir şey bir işareti eklenir Ve anahtar-değer çiftleri dönmelidir azaltabilir. Bu yüzden bu olmalıdır:

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

Bundan sonra, anahtar MlsId ve değeri, bu özel kimliği meydana thimes sayısı olduğu şekilde çıkış anahtar değer çiftleri kümesini sahip olmalıdır. Db.drop() bölümü hakkında emin değilim. İşaret ettiğin gibi, muhtemelen yalnızca çoğaltılmış olanları kaldırmak yerine tüm MlsIds'ı silecektir. Bunu aşmak için önce drop() öğesini arayabilir ve MlsId'yi bir kez yeniden oluşturabilirsiniz. Bu senin için işe yarayacak mı?

+0

ama sonra m ve r fonksiyonları ve ilan etmeleri halinde mapReduce işlevini yürütün ve sonra db [res.result] .drop(); Komut, tüm girişleri mi yoksa sadece yinelenenleri mi indirecek? MapReduce'u anlayamıyorum ve bu yüzden tüm bunların nasıl çalıştığını bilmiyorum ... – Justin

+0

Küçültmek için küçük bir düzeltme yaptım(). Çapa db.drop() çalıştığından emin değilim ama evet, o belirli Id için tüm entried siler sanırım. Ama umarım harita azaltma kısmındaki anlayışınız açıktır. Ben mongodb sözdizimden emin değilim .. bir şey anlayabiliyor mu göreceksiniz .. –

+0

Burada belirtildiği gibi çiftleri kaldır seçeneği ile bir dizin eklemeyi deneyebilirsiniz: http://www.mongodb.org/display/DOCS/ Dizinler Otomatik olarak yinelenen değerleri bırakır.Diğer bir yol, önce tüm değerleri() bırakıp bir değer eklemektir. –

2

Melodb içinde, eşleme için iletilen belgeleri kısıtlamak için bir sorgu kullanabilirsiniz. Muhtemelen umurunda olmayanlar için bunu yapmak istersiniz. Ardından azaltma işlevinde dups'ları yok sayabilir ve yalnızca her bir yinelenen anahtar için dokümanlardan birini döndürebilirsiniz.

Amacınız hakkında biraz kafam karışık. Yalnızca kopyaları bulmak ve bunlardan bir tanesini kaldırmak istiyorsanız, o zaman bu alanda benzersiz bir dizin oluşturabilir ve dropDups seçeneğini kullanabilirsiniz; dizini oluşturma işlemi iki kez dokümanı düşürecektir. Dizini tutmak, bir daha olmayacağından emin olur.

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

+0

Yukarıda belirtildiği gibi, benzersiz dizini dropDups ile kullanamıyorum çünkü yalnızca "" değeri ve bir liste ile bir liste tutuyordu Bunların hepsini tutmak istediğimde "0" değeriyle. – Justin

-1

Sen çiftleri kaldırmak için toplama işlemini kullanabilirsiniz. Gevşeyin, bir kukla $ grubu ve $ sum aşamasını tanıtın ve bir sonraki aşamadaki sayıları dikkate almayın. Böyle bir şey,

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

bu ben yinelemeleri kaldırmak @harri cevap şu nasıl: Bu cevap mümkün olmayabilir

//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 
}); 
İlgili konular