[英]mongodb: matching an element in an array and updating
基本上,我已經完成了聚合以獲取總數和構成總數的對象列表。
現在,我必須使用有助於聚合的元素的聚合對象ID更新源表。 基本上是雙向建立關系。
coll.aggregate([
{ "$match": {"elig": 1, "nid" : null, "cncl" : null } },
{ "$group": {
"_id": "$nkey",
"cumqty": {"$sum": "$pr_qty.qty" },
"netted" : { "$push" : "$_id" }
}},
{ "$project": {
"nkey":"$nkey" ,
"cumqty": "$cumqty",
"netted" : "$netted" ,
"_id" : 0
}},
{ "$out": aggcollnm }
])
現在,聚集表具有由$ push組成的obj id列表。
假設doc1,doc2和doc3組成了agg1,而agg1的列表中有doc1,doc2和doc3。 我希望doc1,doc2和doc3將agg1的ID作為nettid。
所以我做了以下
coll.find().forEach( function(elem) {
coll.update (
{ "_id" : elem._id },
{ "$set" : { nid : aggcoll.aggregate ( [
{ "$unwind" : "$netted" } ,
{ "$match" : { "netted" : elem._id } },
{ "$project" : { "_id" :1 } }
] )._firstBatch[0]
}}
)
})
在較小的范圍內工作正常。 但是對於1M文檔,失敗並顯示以下錯誤。
2014-06-30T09:48:40.577 + 0100錯誤:getMore:服務器上不存在光標,可能重新啟動或超時嗎? 在src / mongo / shell / query.js:116加載失敗:./netting.js
有沒有更好的辦法做到這一點。
您正在運行MongoDB 2.6,因此有許多方法可以更有效地進行更新,並且通常的處理似乎是相反的。 您應該循環“ agggcoll”,然后從中更新目標:
var batch = coll.initializeOrderedBulkOp();
counter = 0;
aggcoll.find().forEach(function(agg) {
batch.find({ "_id": { "$in": agg.netted }}).update({ "$set: { "nid": agg._id } });
counter++;
if ( counter % 1000 == 0 ) {
batch.execute();
counter = 0;
batch = coll.initializeOrderedBulkOp();
}
});
if ( counter > 0 )
batch.execute();
您的“內聯”聚合語句不是一種非常有效的方式來執行您嘗試的操作,並且會大大降低速度。 在這里,不僅通過$in
在所有匹配的_id
值上發出更新$in
因為這是“多”更新操作,而且批量操作API的一般用法減少了服務器的通信量和所花費的時間。
確實,我不知道為什么要這么做,因為您應該已經有了“相關”信息。 看一下您的原始匯總:
{ "$group": {
"_id": "$nkey",
出於某種原因,您對此進行了更改,以便在您將其寫出時不再是該新集合的_id
鍵。 顯然,該字段存在於您從中獲取的所有文檔中,應該只保留它作為新的主鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.