2012-02-10 3 views
1

의 나는이 세 가지 규칙이 있다고 가정 해 봅시다 :mongodb - mapreduce로 논리적 규칙을 처리하고 있습니까?

[{ 
    selector: {_id: "1"}, 
    value: {name: "apple"} 
}, 
{ 
    selector: {name: "apple"}, 
    value: {type: "fruit"} 
}, 
{ 
    selector: {type: "fruit"}, 
    value: {class: "food"} 
}] 

나는이 결과로 끝날 싶습니다 :

{ 
    _id: 1, 
    value: { 
     name: "apple", 
     type: "fruit", 
     class: "food" 
    } 
} 

내가 맵리 듀스 함께 할 수 있을까요?

+0

나는 줄일 수 있다고 확신한다. –

+0

이 조인처럼 보입니다. mongodb는 비정규 화 된 데이터를 저장한다는 아이디어를 바탕으로 만들어 졌으므로 잘못된 방식으로 데이터를 정렬 할 수 있습니다 ... – Kevin

+0

이 경우 조인이 가능하지만 임의로 길고 복잡한 객체 목록을 생성하는 데 관심이 있습니다. 규칙 목록. 이것은보다 복잡한 유스 케이스의 총체적인 단순화이다. –

답변

0

내 문제는 여기에 있습니다 (mongodb 드라이버가있는 node.js). 나는 그것이 꽤 최적화 될 수 있다고 확신한다.

var logicize = function(db, callback) { 
    var reduce = function(key, values){ 
     // If values is an array of objects, it is merged into a single object 
     if(values.length) { 
      while(values.length>1) { 
       var current = values.pop(); 
       for (var property in current) { 
        values[0][property] = current[property]; 
       } 
      } 
      return values[0]; 
     } 
     return values; 
    }; 

    db.collection("rules", function(err, rules) { 
     db.collection("results", function(err, results) { 
      rules.mapReduce("function() {emit(this.selector._id, this.value);}", reduce, {out: {replace:"results"}, query:{"selector._id":{$exists:true}}}, function() { 
       rules.find({"selector._id":{$exists:false}}, function(err, cursor) {    
        cursor.nextObject(function(err, item) { 
         // Recursive because I don't want to start a new mapreduce 
         // before the previous one has finished. The following one 
         // might depend on the results of the previous 
         (function recurse(item) { 
          if(item==null) // Done 
           callback(); 
          else { 
           var map = new Function('emit(this._id, '+JSON.stringify(item.value)+');'); 

           var conditions = {}; 
           for(var condition in item.selector) { 
            conditions['value.'+condition] = item.selector[condition]; 
           } 
           results.mapReduce(map, reduce, {out:{reduce:"results"},query: conditions}, function() { 
            // Previous mapreduce has finished so we can start the next one 
            cursor.nextObject(function(err, item) { 
             recurse(item); 
            }); 
           }); 
          } 
         })(item); 
        }); 
       }); 
      }); 
     }); 
    }); 
} 

규칙은 "규칙"모음에 있으며 결과는 "결과"로 이동합니다. 나는 _id가있는 규칙만으로 초기 mapreduce를 수행하고 있습니다. 그 후에 다른 규칙마다 별도의지도 축소를 실행합니다.

0

당신은 모든 객체에 대해 임의의 자바 스크립트를 실행할 수 있기 때문에 mapreduce로 원하는 것을 할 수 있습니다. 그러나 mapreduce가 현재로서는 그리 빠르지 않다는 것을 알고 있어야하며 map/reduce 함수 내에서 "db"연산을하지 않는 것이 좋습니다 (샤딩과 일관성이 없으며 잠금 문제를 만들 수 있음).

첫 번째 단계는 데이터의 일부를 복제한다고해도 미리 채워지도록 데이터를 모델링하는 것이 가장 이상적입니다. 그렇게 할 수 없다면 mapreduce와 작업 클라이언트 측의 속도를 비교해야합니다.