Попытка отфильтровать значения массива в массиве в MongoDB - PullRequest
0 голосов
/ 03 мая 2020

Я новичок в MongoDB и пытаюсь отфильтровать значения массива в массиве. Пример схемы приведен ниже. Схема в основном представляет собой дамп трехуровневого словаря с простым объектом скаляров в качестве конечного узла.

Член "I" содержит массив документов (внешний массив) пар ключ-значение со строковым ключом (k), а значение (v) представляет собой массив документов (средний массив) ключа пары-значения с датой в качестве ключа и значением - это еще один словарь, который не является частью этого вопроса.

По сути, мне нужно получить самые последние данные из среднего массива (Date, ключ-значение) для данного значения внешнего массива (строка, ключ-значение).

(Collection Sample)
{
    "_id" : ObjectId("5eacfbe62758834aefdec003"),
    "UserId" : UUID("46942978-29f4-4521-9932-840cead6743e"),
    "Data" : {
        "I" : [
            {
                "k" : "LRI39",
                "v" : [
                    {
                        "k" : ISODate("2020-03-11T20:24:41.591Z"),
                        "v" : [
                            {
                                "k" : ISODate("2020-03-11T20:24:41.594Z"),
                                "v" : {
                                    "Source" : 1,
                                    "Value" : 19
                                }
                            }
                        ]
                    },
                    {
                        "k" : ISODate("2020-01-22T11:37:23.393Z"),
                        "v" : [
                            {
                                "k" : ISODate("2020-01-22T11:37:23.412Z"),
                                "v" : {
                                    "Source" : 1,
                                    "Value" : 20
                                }
                            }
                        ]
                    }
                ]
            },
            ...
        ]
    }
}

Мне удалось создать документ, который в основном то, что вы видите от «данных» до конца примера, являясь полной записью для LRI39, используя:

db.threetier.aggregate([
{   
    $project: {
        "Data.I": {
            $filter: {
                input: "$Data.I",
                as: "item",
                cond: {
                    $eq: [ "$$item.k", "LRI39" ]                        
                }
            }
        }
    }
}
])

Однако, независимо от того, что я делаю, я не могу вернуть какое-либо подмножество записей среднего массива: я получаю 2020- Элементы 03-11 и 2020-01-22, или я ничего не получаю.

Я попытался добавить этапы, подобные приведенным ниже, к проекции выше, полагая, что я получу 1 запись (запись 2020-01-22) но я получаю оба. Если я изменю дату на 2019 год, я ничего не получу (как и ожидалось).

$project: {
    "Data.I.v": {
        $filter: {
            input: "$Data.I.v",
            as: "stamp",
            cond: { $lt: [ "$$stamp.k", ISODate("2020-02-14T00:00:00Z") ] }             
        } 
    }
}   

Я также попытался:

{ $match: { $expr: { $lt: [ "Data.I.v.k", ISODate("2020-02-14T00:00:00Z") ] } } }

, но это не дает результатов вообще (вероятно, потому что $ match работает с документами, а не с массивами), а также пытается развернуть массив, используя $unwind: "$Data.I.v" перед совпадением, но это также ничего не возвращает.

Кажется, здесь я упустил что-то фундаментальное. Я понимаю, что Mon go разработан (я думаю), чтобы иметь эти элементы массива в качестве документов, но я хочу посмотреть, будет ли это работать как есть.

1 Ответ

0 голосов
/ 03 мая 2020

Вам нужно будет развернуть и Data.I, и Data.I.v, чтобы можно было рассмотреть каждый из подэлементов по отдельности.

Затем выполнить обратную сортировку по полю даты. Группируйте по _id и ключу, выбирая только первый документ в каждой группе. Наконец, замените Root, чтобы возврат был только выбранным документом.

db.collection.aggregate([
  {$unwind: "$Data.I"},
  {$unwind: "$Data.I.v"},
  {$sort: {"Data.I.v.k": -1}},
  {$group: {
      _id: {
        _id: "$_id",
        key: "$Data.I.k"
      },
      document: {$first: "$$ROOT"}
  }},
  {$replaceRoot: {newRoot: "$document"}}
])

Детская площадка

...