Ключевое правило «отобразить / уменьшить» в любой реализации в основном заключается в том, что одна и та же форма данных должна быть отправлена маппером , что также возвращается редуктор . Ключевая причина этого заключается в том, что концептуально работает схема "map / Reduce", вполне возможно, вызывая reducer несколько раз. Это означает, что вы можете вызывать функцию reducer на выходе, который уже был получен из предыдущего прохода через reducer вместе с другими данными из mapper .
MongoDB может вызывать функцию уменьшения более одного раза для одной и той же клавиши. В этом случае предыдущий вывод из функции уменьшения для этой клавиши станет одним из входных значений для следующего вызова функции уменьшения для этой клавиши.
Тем не менее, ваш лучший подход к «среднему» - это, следовательно, итого данных вместе с count , а затем просто разделить их. Это фактически добавляет еще один шаг к операции «сопоставление / уменьшение» как finalize function.
db.football_team.mapReduce(
// mapper
function() {
emit(this.gender, { count: 1, weight: this.weight });
},
// reducer
function(key,values) {
var output = { count: 0, weight: 0 };
values.forEach(value => {
output.count += value.count;
output.weight += value.weight;
});
return output;
},
// options and finalize
{
"out": "gender_stats", // or { "inline": 1 } if you don't need another collection
"finalize": function(key,value) {
value.avg_weight = value.weight / value.count; // take an average
delete value.weight; // optionally remove the unwanted key
return value;
}
}
)
Все в порядке, потому что оба преобразователя mapper и излучают данные с одинаковой формой , а также ожидают ввода в этой форме в пределах Редуктор Сам. Конечно, метод finalize вызывается только после того, как все «сокращение» наконец выполнено и просто обрабатывает каждый результат.
Как уже отмечалось, метод aggregate()
на самом деле делает это гораздо более эффективно и в методах с собственным кодированием, которые не несут накладных расходов (и потенциальных угроз безопасности) при интерпретации и исполнении JavaScript на стороне сервера:
db.football_team.aggregate([
{ "$group": {
"_id": "$gender",
"count": { "$sum": 1 },
"avg_weight": { "$avg": "$weight" }
}}
])
И это в основном все. Более того, вы можете продолжать и делать другие вещи после a $group
этапа конвейера (или любого этапа в этом отношении) способами, которые вы не можете сделать с реализацией MongoDB mapReduce
. Что-то вроде применения $sort
к результатам:
db.football_team.aggregate([
{ "$group": {
"_id": "$gender",
"count": { "$sum": 1 },
"avg_weight": { "$avg": "$weight" }
}},
{ "$sort": { "avg_weight": -1 } }
])
Единственная сортировка , разрешенная mapReduce
, заключается только в том, что ключ , используемый с emit
, это всегда , отсортированный в по возрастанию порядок. Но вы не можете сортировать агрегированный результат в выводе любым другим способом, конечно, не выполняя запросы при выводе в другую коллекцию или работая "в памяти" с возвращенными результатами с сервера .
В качестве "дополнительного примечания" (хотя и важного), вы, вероятно, также должны учитывать при "изучении" , что реальность - это "серверный JavaScript « функциональность MongoDB действительно обходной путь больше, чем функция . Когда MongoDB был впервые представлен, он применил движок JavaScript для выполнения сервера, главным образом, чтобы компенсировать функции , которые еще не были реализованы.
Таким образом, к компенсируется отсутствие полной реализации многих операторов запросов и функций агрегирования, которые появятся позже, добавление механизма JavaScript было "быстрым исправлением" , чтобы позволить некоторые вещи должны быть выполнены с минимальной реализацией.
Результатом стало то, что функции движка JavaScript постепенно удаляются. Функция group()
API удалена. Функция eval()
API устарела и планируется удалить в следующей основной версии. В основном это "на стене" для ограниченного будущего этих функций JavaScript на сервере, поскольку ясная схема - это когда функции native что-то поддерживают, тогда возникает необходимость продолжение поддержки движка JavaScript в основном исчезает.
Основная мудрость здесь заключается в том, что фокусировка на изучении этих JavaScript на серверных функциях, вероятно, не стоит потраченного времени, если у вас нет неотложного варианта использования, который в настоящее время не может быть решен никакими другими средствами.