получить последнее имя, оценка - PullRequest
2 голосов
/ 27 сентября 2010

У меня есть коллекция mongodb, которая выглядит примерно так:

db.scores.insert({"name": "Bob", value: 96.3, timeStamp:'2010-9-27 9:32:00'})
db.scores.insert({"name": "John", value: 98.3, timeStamp:'2010-9-27 9:28:00'})
db.scores.insert({"name": "Bob", value: 99.3, timeStamp:'2010-9-27 9:29:00'})
db.scores.insert({"name": "John", value: 97.3, timeStamp:'2010-9-27 9:31:00'})

Как я могу запросить это, чтобы дать мне каждое имя один раз с самым последним значением:

{name: "John", value: 97.3}
{name: "Bob", value: 96.3}

1 Ответ

5 голосов
/ 28 сентября 2010

Вы пытаетесь выполнить агрегацию данных, поэтому вам нужно написать запрос уменьшения карты .

Отображение

Функция 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...