2015-10-19 22 views
0

我有以下結構:的MongoDB - 更新中的第二級陣列

document: { 
    'data': { 
     'field_1': 'blabla', 
     'field_2': 'blabla++', 
     'interesting_field': [ 
      { 
       'f_1': 'abc', 
       'this_is_interesting': [ 
         { 
         'a1': 'text', 
         'a2': 'other_text' 
         }, 
         { 
         'a1': 'text 2', 
         'a2': 'text 3' 
         } 
       ] 
      }, 
      'etc': 'etc' 
     ] 
    }, 
    'somthing_boring': 'bla' 
} 

我需要做的就是更新所有「A2」從「interesting_field」域「this_is_interesting」(如果它們符合特定標準)。

要在1級陣列更新,我可以這樣做:

{ 
    '_id': new ObjectId('5621020d78946ac20a000021'), 
    'data.interesting_field' : { 
    $elemMatch : { 
     'f_1' : 'abc' 
    } 
    } 
}, 
{$set: {'data.interesting_field.$.something_to_update': 'something'}} 

但是......看來我不能使用匹配水平2+陣列。任何想法如何做到這一點? (正在考慮mapReduce ...但不認爲我可以在更新查詢中使用它)。

+0

你的文件是無效的。是'this_is_interesting'數組的子文檔嗎? – styvane

+0

我的不好,固定... – zozo

回答

2

正如您所述,您通常會使用位置運算符$來執行此操作。

不幸的是,現在位置運算符只支持一個數組深度的匹配。

有一個JIRA票,你想要的那種行爲:https://jira.mongodb.org/browse/SERVER-831

如果你希望能夠改變匹配的元素在this_is_interesting,你必須改變你的數據的結構 - 無論是展平,或將其分爲兩個集合。

編輯:其實,你可以使用MapReduce的進行更新,因爲在這個答案說明:https://stackoverflow.com/a/33172255/236660

但是,這將是非常,非常低效的。我建議你改組你的數據。

+0

我知道...但我想到另一個解決方案...像...找到我需要的子文檔,使用$拉刪除它(拉接受一個更多的條件,所以我期望它的工作??然後推它的修改後的版本)。基本上... 2中的查詢不幸的是,我沒有設法使它工作。 注意:很明顯,子文檔順序對我來說並不重要。或者......正如我所說的那樣,使用地圖縮小。 注2:舊數據庫,重構數據意味着重構代碼,atm是沒有問題的。 – zozo

+0

@zozo,我添加了一個鏈接到一個類似的問題的答案:http://stackoverflow.com/a/33172255/236660 - 希望可以幫助你 –

+2

是我心中的那種:)。如果我設法使其工作應該沒問題。我會在幾個小時內接受答案 - 也許一個更簡單的解決方案將呈現自己,如果不是的話......沒問題。 – zozo

1

那麼假設你想更新你的集合中的所有文檔,其中a2: 'other_text'a2的值設置爲new_other。使用文檔的實際結構,您需要遍歷集合中的每個文檔,然後針對interesting_field陣列中的每個元素,然後針對this_is_interesting陣列中的每個元素檢查a2的值是否與給定條件匹配,在這種情況下,您更新相應的子 - 使用所謂的"dot notation""bulk"操作獲得最大效率。您必須動態構建您的查詢才能正常工作。

var bulkOp = db.collection.initializeOrderedBulkOp(); 
var count = 0; 

db.collection.find({ "document.data.interesting_field.this_is_interesting.a2": 'other_text' }).forEach(function(doc) { 
    var interesting_field = doc.document.data.interesting_field; 
    var size = interesting_field.length; 
    for(var ind=0; ind < size; ind++) {  
     var this_is_interesting = doc.document.data.interesting_field[ind]['this_is_interesting'];  
     for(var ix=0; ix < this_is_interesting.length; ix++) { 
      if(this_is_interesting[ix]['a2'] === 'other_text') { 
       var updateDocument = {}; 
       updateDocument['document.data.interesting_field.' + ind + '.this_is_interesting.' + ix + '.a2'] = 'new_other';  
       bulkOp.find({'_id': doc._id}).update({ 
        '$set': updateDocument 
       });    
       count++;   
      }  
     }  
     if(count % 200 === 0) { 
      // Execute per 200 operations and re-init  
      bulkOp.execute();   
      bulkOp = db.collection.initializeOrderedBulkOp();  
     } 
    } 
}) 

// Clean up queues 

if(count > 0) { 
    bulkOp.execute(); 
} 

但要做到的最好的事情是改變你的文件結構