#mongodb #aggregation-framework
#mongodb #структура агрегации
Вопрос:
У меня есть коллекция MongoDB, в которой документы имеют вид:
{
year: 1900,
alabama: 145,
arkansas: 103,
// ... for all 50 US states
}
Я хотел бы получить запрос, который выдает сумму по коллекции для каждого состояния. Таким образом, результат может выглядеть так:
{
alabama: 1360492,
arkansas: 598023,
// ... and so on
}
Лучшее, что я смог придумать, — это агрегированный запрос с 50 терминами:
db.sample.aggregate({$group: {
_id: "",
alabama: {$sum: "$alabama"},
arkansas: {$sum: "$arkansas"},
// ... and so on
}});
Есть ли какой-нибудь способ построения запроса, который позволяет мне просто предоставить массив имен полей, которые необходимо суммировать?
Ответ №1:
Я не знаю, как это сделать, используя структуру агрегации, но используя mapreduce, это довольно просто;
> db.test.insert({ year: 1900, alabama: 145, arkansas: 103 })
> db.test.insert({ year: 1901, alabama: 100, arkansas: 77 })
// Map function, emits the state name and the value for each entry
> var m = function () {
for(var key in this) {
if(this.hasOwnProperty(key) amp;amp;
key != 'year' amp;amp; key!='_id')
emit(key, this[key])
}
}
// Reduce function, just sums up the score per state
> var r = function (state, score) { return Array.sum(score); }
// Run mapreduce with map function m, reduce function r, and output inline
> db.test.mapReduce(m, r, {out:{inline:1}})
{
"results" : [
{
"_id" : "alabama",
"value" : 245
},
{
"_id" : "arkansas",
"value" : 180
}
]
}
РЕДАКТИРОВАТЬ: чтобы иметь возможность использовать структуру агрегации, я не вижу способа без незначительного изменения модели данных, чтобы иметь возможность доступа к состоянию в качестве ключа;
> db.test2.insert({ year: 1900, data:[{k:"alabama", v:145},
{k:"arkansas", v:103}] } )
> db.test2.insert({ year: 1901, data:[{k:"alabama", v:100},
{k:"arkansas", v:77}] } )
// Unwind data, and group it back together by key while summing the values;
> db.test2.aggregate({$unwind:"$data"},
{$group:{_id:"$data.k",total:{$sum: "$data.v"}}})
{ "_id" : "arkansas", "total" : 180 }
{ "_id" : "alabama", "total" : 245 }
Комментарии:
1. Есть ли у вас какая-либо интуиция относительно того, как это будет сравниваться с точки зрения производительности со структурой агрегации?
2. @TomPanning Структура агрегации обычно работает быстрее, если вы можете написать эквивалентный запрос, однако в этом случае я не знаю способа сделать это с существующей моделью данных.
3. @TomPanning добавил способ использования агрегации при незначительном изменении модели данных.