2016-11-15 103 views
1

我有非常複雜的查詢,我試圖編寫,似乎無法將我的頭圍繞寫入它的最佳方式。最終,我試圖避免必須手動全部寫出來。我想要做的是採取一個動態的領域,並通過每個文件,看看這個領域是否存在,如果它確實然後更新它。問題在於該字段在文檔中可能存在多次,因爲它可以在嵌入式級別上存在於每個單獨父文檔的多個嵌入式文檔中。根據匹配查詢更新所有文檔和嵌入文檔中的字段MongoDB NodeJS

這裏是一個典型的對象是什麼樣子:

applications: { 
    _id: 5368hss76sd9f, 
    ProgramAreaId: 1, 
    ProgramArea: 'Education', 
    StrategyId: 16, 
    Strategy: 'Graduate Program', 
    AlternateMapping: [{ 
     ProgramAreaId: 2, 
     ProgramArea: 'Private Sector', 
     StrategyId: 13, 
     Strategy: 'Higher Education Fund' 
    }], 
    Funding: [{ 
     Amount: '500000' 
     StrategyId: 16 
     Strategy: 'Graduate Program' 
     }, 
     { 
     Amount: '500000' 
     StrategyId: 13 
     Strategy: 'Higher Education Fund' 
     } 
    ] 
} 

我可能有這些,我將需要一次更新幾千。最終目標是在一個查詢中完成。我已經讓它在基本級別的單個字段上工作,但想知道是否有辦法使它適用於所有與動態名稱匹配的字段,即使在嵌入式文檔中也是如此。

這裏是我到目前爲止已經試過:

 var fieldId = obj.Type + 'Id'; //obj.Type could equal 'Strategy' or 'ProgramArea' 
    var field = obj.Type; 
    var id = 13; //This could be any number of ids and ultimately was what I want to match on. 
     var qry = { 
      $where: function() { 
       var deepIterate = function(o, value) { 
        for (var field in o) { 
         if (field == fieldId && obj[field] == value) { 
          console.log() 
          return true; 
         } 
         var found = false; 
         if (typeof o[field] === 'object') { 
          found = deepIterate(o[field], value) 
          if (found) { 
           return true; 
          } 
         } 
        } 
        return false; 
       }; 
       return deepIterate(this, id) 
      } 
     }; 

     var setQry = { $set: {} }; 
     setQry.$set[field] = obj.Name;//Field here would be 'Strategy' or 'ProgramArea' or any number of other fields I could be updateing and Name is what I want the value of that field to equal. 

     mongo.collection('applications').updateMany(qry, setQry, function(err, result) { 
      if (err) 
       callback(null); 
      else 
       callback(result); 
     }); 

上面的查詢會找到我任何「應用」,它包含的字段名稱相同的字段名稱我要求的,它甚至會通過搜索嵌入文檔以查看該字段是否存在。上述查詢的問題是,它只會更新父級別上的該字段,而不是更新子級。

回答

0

所以我想我已經找到了上述代碼的最佳解決方案。我創建了下面的代碼來完成上面的問題,它的功能非常好!

var resultsArray = []; 
var fieldId = obj.Type + 'Id'; 
var field = obj.Type; 
if (coll == 'statuses') { 
    fieldId = "StatusId"; 
    field = "Status"; 
} 

var altmapField = 'AltMaps.' + fieldId, 
    altfundField = 'AltFunds.' + fieldId, 
    paymentField = 'Payments.' + fieldId, 
    reportField = 'Reports.' + fieldId, 
    crosswalkField = 'Crosswalk.' + fieldId, 
    regionField = 'RegionBreakdowns.' + fieldId, 
    sectorField = 'SectorBreakdowns.' + fieldId; 
var qry = []; 
qry.push({ 
    $match: { 
     $or: [{ 
     }, { 
     }, { 
     }, { 
     }, { 
     }, { 
     }, { 
     }, { 
     }] 
    } 
}); 

qry[0].$match.$or[0][fieldId] = id; 
qry[0].$match.$or[1][altmapField] = id; 
qry[0].$match.$or[2][altfundField] = id; 
qry[0].$match.$or[3][paymentField] = id; 
qry[0].$match.$or[4][reportField] = id; 
qry[0].$match.$or[5][crosswalkField] = id; 
qry[0].$match.$or[6][regionField] = id; 
qry[0].$match.$or[7][sectorField] = id; 


var cursor = mongo.collection(collectionPrefix + 'applications').aggregate(qry, { allowDiskUse: true, explain: false }, null); 

基本上我所做的就是動態地構建出一個查詢,然後傳遞到蒙戈集合,它讀取它像一個冠軍。