2016-11-15 1 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); 

는 기본적으로 내가 한 모든 동적 쿼리를 구축하고 몽고 집계에 그 전달했다 그리고 그것은 챔피언처럼 읽어 보시기 바랍니다.

관련 문제