Mongodb: выберите последнее событие из временного ряда

Я пытаюсь построить временной ряд в базе данных Mongo и, основываясь на советах из нескольких сообщений SO, я использую один документ для каждого события, например:

{
  _id: ObjectId("51a67033868eda7666b0a49c"),
  station_id: 12,
  timestamp: ISODate("2013-05-29T21:16:35.929Z"),
  value: 50
}

Получить историю для конкретной станции достаточно просто(db.mydata.find({station_id: 12}, {timestamp: 1})).

Более сложной задачей является получение последнего значения на всех моих станциях. (Обратите внимание, что последняя отметка времени будет разной для каждой станции, поэтому я не могу выполнить наивный запрос.) В SQL я бы сделал:

SELECT station_id, timestamp, value
FROM mydata
WHERE (station_id, timestamp) IN (
  SELECT station_id, MAX(timestamp)
  FROM mydata
  GROUP BY station_id
)

Как бы вы сделали что-то подобное в MongoDB? Структура агрегации довольно мощная, но я не могу найти способ использовать ее для такого типа анализа.

Большое спасибо за любую помощь.


person Maan    schedule 31.05.2013    source источник


Ответы (2)


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

db.mydata.aggregate( [
      { $sort : {timestamp:-1}},
      { $group : { _id : "$station_id",
                 timestamp : {$first:"$timestamp"},
                 value : {$first:"$value"}
      }  }
] )

По сути, вы сортируете свой ввод по отметке времени по убыванию, а затем агрегируете, и для каждого уникального station_id вы сохраняете первую отметку времени и значение, с которым вы сталкиваетесь (в порядке сортировки!)

person Asya Kamsky    schedule 01.06.2013

SELECT station_id, timestamp, value
FROM mydata
WHERE (station_id, timestamp) IN (
  SELECT station_id, MAX(timestamp)
  FROM mydata
  GROUP BY station_id
)

думаю будет что-то похожее на

db.aggregate( 
    { $group : { _id : "$station_id", max_timestamp : { $max : timestamp } } },
    { $project : {station_id : 1, max_timestamp : 1, value : 1 } }
)
person Lucia Pasarin    schedule 31.05.2013
comment
это не сработает - у вас есть только station_id и временная метка, выходящие из фазы $group. Вы не можете проецировать ценность, поскольку не сохранили ее. - person Asya Kamsky; 01.06.2013
comment
Ты прав. Я думал, что могу что-то потерять из-за того, что нахожусь на другом уровне агрегации, но я не подумал о вашем решении. Я думаю, что это единственный способ, +1 за это. - person Lucia Pasarin; 01.06.2013