使用聚合框架的問題是,您無法爲對象的屬性指定任意的鍵名稱。因此,如果不能指定所有可能的密鑰名稱,就不可能重新使用它。
因此,要獲得你需要努力的東西在JavaScript中,如mapReduce
結果:
首先定義一個映射:
var mapper = function() {
var key = this["class"];
delete this._id;
delete this["class"];
emit(key, this);
};
然後減速:
var reducer = function (key, values) {
var reducedObj = {};
values.forEach(function(value) {
if (!reducedObj.hasOwnProperty(value.type))
reducedObj[value.type] = [];
reducedObj[value.type].push(value.Name);
});
return reducedObj;
};
而且,因爲您(至少在您的示例中)只有一個鍵值y的映射器將會發射可能的項目歐還需要一個finalize函數:
var finalize = function (key,value) {
if (value.hasOwnProperty("name")) {
value[value.type] = value.name;
delete value.type;
delete value.name;
}
return value;
};
然後調用MapReduce的功能如下:
db.collection.mapReduce(
mapper,
reducer,
{ "out": { "inline": 1 }, "finalize": finalize }
)
這給出了以下的輸出:
"results" : [
{
"_id" : "class A",
"value" : {
"type 1" : [
"ObjectA1"
],
"type 2" : [
"ObjectA2_1",
"ObjectA2_2"
]
}
},
{
"_id" : "class B ",
"value" : {
"type" : "type 3",
"Name" : "ObjectB3"
}
}
],
雖然結果被格式化在一個非常mapReduce的方式,它肯定與你的結果相同。
但是,如果你真的想進一步採取,你總是可以做到以下幾點:
定義其他製圖:
var mapper2 = function() {
emit(null, this);
};
而另一減速機:
var reducer2 = function (key,values) {
reducedObj = {};
values.forEach(function(value) {
reducedObj[value._id] = value.value;
});
return reducedObj;
};
然後運行第一個mapReduce與輸出到一個新的集合:
db.collection.mapReduce(
mapper,
reducer,
{ "out": { "replace": "newcollection" }, "finalize": finalize }
)
之後的第二MapReduce的在新的集合:
db.newcollection.mapReduce(
mapper2,
reducer2,
{ "out": { "inline": 1 } }
)
而且有你的結果:
"results" : [
{
"_id" : null,
"value" : {
"class A" : {
"type 1" : [
"ObjectA1"
],
"type 2" : [
"ObjectA2_1",
"ObjectA2_2"
]
},
"class B " : {
"type" : "type 3",
"Name" : "ObjectB3"
}
}
}
],