2012-02-10 81 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" 
    } 
} 

我能做到這一點與MapReduce的?

+0

我很確定你可以用減少來做到這一點。 – 2012-02-10 19:40:55

+0

看起來像一個連接,是你想要做什麼? mongodb是圍繞存儲非規範化數據的想法構建的,因此您可能會以錯誤的方式安排數據... – Kevin 2012-02-10 19:43:54

+0

在這種情況下,聯接可以工作,但我有興趣從任意長和複雜的對象中生成對象列表規則列表。這是對更復雜用例的簡化。 – 2012-02-10 19:48:14

回答

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); 
        }); 
       }); 
      }); 
     }); 
    }); 
} 

規則在「規則」集合中,結果進入「結果」。我首先執行的初始mapreduce只有一個_id的規則。之後,我爲每個其他規則運行單獨的mapreduce。

0

因爲您可以在所有對象上執行任意的JavaScript,所以您幾乎可以用mapreduce做任何事情。但是你應該知道mapreduce現在不是很快,並且建議不要在map/reduce函數中執行「db」操作(與分片不一致,並且可能會產生鎖定問題)。

理想情況下,第一步是嘗試對數據進行建模,以便預填充數據,即使這意味着重複某些數據。如果這是不可能的,你應該比較mapreduce和做客戶端工作的速度。