С MongoDB 3.6 вы можете использовать $objectToArray
и $arrayToObject
, чтобы разделить объекты и накапливать:
db.collection.aggregate([
{ "$project": {
"data": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$ne": [ "$$this.k", "_id" ] }
}
}
}},
{ "$unwind": "$data" },
{ "$group": {
"_id": "$data.k",
"v": { "$sum": "$data.v" }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"data": { "$push": { "k": "$_id", "v": "$v" } }
}},
{ "$replaceRoot": {
"newRoot": { "$arrayToObject": "$data" }
}}
])
Возвращает:
{ "x" : 4, "y" : 30, "z" : 13 }
То же самое в основном с mapReduce()
, если у вас нет MongoDB, поддерживающей эти операторы:
db.collection.mapReduce(
function() {
var doc = this;
delete doc._id;
emit(null, doc);
},
function(key,values) {
var output = {};
values.forEach(value =>
Object.keys(value).forEach(k => {
if (!output.hasOwnProperty(k))
output[k] = 0;
output[k] = output[k] + value[k];
})
);
return output;
},
{ "out": { "inline": 1 } }
)
Немного другой вывод в стиле mapReduce:
{
"_id" : null,
"value" : {
"x" : 4,
"y" : 30,
"z" : 13
}
}