Вы пытаетесь выполнить агрегацию данных, поэтому вам нужно написать запрос уменьшения карты .
Отображение
Функция map в основном является предложением GROUP BY
из SQL. В вашем случае мы сгруппируемся по имени, поэтому мы будем использовать имя как key
. value
будет содержать другие необходимые нам данные, в данном случае это значение и метка времени.
map = function () {
emit(this.name, { timeStamp: this.timeStamp, value: this.value });
}
Функция карты приведет к массиву значений для каждого ключа. Поэтому все документы с именем «Боб» сопоставляются с ключом «Боб». Для ваших примеров данных результат может выглядеть следующим образом:
{ _id: "Bob", values: [
{ timeStamp: "2010-9-27 9:32:00", value: 96.3 },
{ timeStamp: "2010-9-27 9:29:00", value: 99.3 }
]},
{ _id: "John", values: [
{ timeStamp: "2010-9-27 9:28:00", value: 98.3 },
{ timeStamp: "2010-9-27 9:31:00", value: 97.3 }
]},
Снижение
Функция Reduce отвечает за приведение массива значений для каждого ключа к одному значению. В вашем случае нас интересуют только данные с самой высокой отметкой времени:
reduce = function (key, values) {
var maxData = { timeStamp: new Date(0) };
values.forEach(function (data) {
if (data.timeStamp > maxData.timeStamp) {
maxData = data;
}
});
return maxData;
}
Обратите внимание, что важно, чтобы возвращаемое значение функции приведения было в том же формате, что и принимаемые значения. Это связано с тем, что функция уменьшения может вызываться несколько раз для одной клавиши, каждый раз принимая только сегмент общих значений.
Запуск функции уменьшения приведет к следующему:
{ _id: "Bob", value: { timeStamp: "2010-9-27 9:32:00", value: 96.3 } },
{ _id: "John", value: { timeStamp: "2010-9-27 9:31:00", value: 97.3 } }
Доработка
Функция финализатора может использоваться для извлечения только тех данных, которые нам нужны. Это значение.
finalize = function (key, value) {
return value.value;
}
Это приведет к:
{ "_id" : "Bob", "value" : 96.3 },
{ "_id" : "John", "value" : 97.3 }
Запуск карты-уменьшения
Вы можете запустить сокращение карты с помощью следующих функций:
res = db.scores.mapReduce(map, reduce, { finalize: finalize });
Коллекция db[res.result]
будет содержать результат запроса.
Последняя проблема
Функция уменьшения сравнивает временные метки как Объекты даты . Судя по вашему примеру кода, вы сохранили метки времени в виде строки вместо объектов Date или целочисленных меток времени. Поэтому, прежде чем вы сможете сравнить даты, вам нужно будет преобразовать эти строки в объекты Date.