這是我對這個問題的看法(帶有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。
我很確定你可以用減少來做到這一點。 – 2012-02-10 19:40:55
看起來像一個連接,是你想要做什麼? mongodb是圍繞存儲非規範化數據的想法構建的,因此您可能會以錯誤的方式安排數據... – Kevin 2012-02-10 19:43:54
在這種情況下,聯接可以工作,但我有興趣從任意長和複雜的對象中生成對象列表規則列表。這是對更復雜用例的簡化。 – 2012-02-10 19:48:14