2012-02-10 12 views
1

のは、私はこれらの3つのルールがあるとしましょう: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

私はあなたがreduceでそれを行うことができると確信しています。 –

+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を持つルールだけで初期のマップリダクションを実行しています。その後、別のルールごとにマップリダクションを実行しています。

0

すべてのオブジェクトに対して任意のjavascriptを実行できるので、mapreduceで必要なことを行うことができます。しかし、mapreduceは今はあまり速くないことに注意してください。マップ/リダクション関数内で "db"演算をしないようにすることをお勧めします(シャーディングと矛盾し、ロックの問題を引き起こす可能性があります)。

第1のステップは、データの一部を複製することを意味していても、データがあらかじめ入力されるようにモデル化するのが理想的です。それが不可能な場合は、mapreduceと作業クライアント側の速度を比較する必要があります。

関連する問題