Запрос монго для обнаружения изменений значений во временных рядах - PullRequest
1 голос
/ 10 апреля 2019

Мне интересно, возможно ли следующее в MongoDB.

У меня есть коллекция документов, которые представляют изменения в некотором значении во времени:

{
  "day" : ISODate("2018-12-31T23:00:00.000Z"),
  "value": [some integer value]
}

Нет никаких «дырок» вданные, у меня есть записи для всех дней в некотором периоде.

Можно ли запросить эту коллекцию, чтобы получить только те документы, которые имеют значение, отличное от предыдущего (при сортировке по дням asc)?Например, имея следующие документы:

{
      "day" : ISODate("2019-04-01T00:00:00.000Z"),
      "value": 10
},
{
      "day" : ISODate("2019-04-02T00:00:00.000Z"),
      "value": 10
},
{
      "day" : ISODate("2019-04-03T00:00:00.000Z"),
      "value": 15
},
{
      "day" : ISODate("2019-04-04T00:00:00.000Z"),
      "value": 15
},
{
      "day" : ISODate("2019-04-05T00:00:00.000Z"),
      "value": 15
},
{
      "day" : ISODate("2019-04-06T00:00:00.000Z"),
      "value": 10
}

Я хочу получить документы на 2018-04-01, 2018-04-03 и 2018-04-06.

Я отправляю этот вопросеще раз, потому что предыдущий был ошибочно помечен как дубликат.

1 Ответ

2 голосов
/ 10 апреля 2019

Вам нужно получить пары последовательных документов, чтобы обнаружить пробел.Для этого вы можете поместить все документы в один массив, и zip сам сместит с головы на 1 элемент:

db.collection.aggregate([
    { $sort: { day: 1 } },
    { $group: { _id: null, docs: { $push: "$$ROOT" } } },
    { $project: {
        pair: { $zip: {
            inputs:[ { $concatArrays: [ [false], "$docs" ] }, "$docs" ]            
        } }
    } },
    { $unwind: "$pair" },
    { $project: {
        prev: { $arrayElemAt: [ "$pair", 0 ] },
        next: { $arrayElemAt: [ "$pair", 1 ] }
    } },
    { $match: {
         $expr: { $ne: ["$prev.value", "$next.value"] } 
    } },
    { $replaceRoot:{ newRoot: "$next" } }
])

Остальное тривиально - вы раскручиваете массив обратно в документыСравните пары, отфильтруйте равные и replaceRoot из того, что осталось.

...