簡體   English   中英

mongodb:匹配數組中的元素並更新

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM