MongoDB: Как я могу агрегировать значения узлов вложенных произвольных объектов kv, используя агрегированный конвейер? - PullRequest
0 голосов
/ 23 января 2019

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

Для дополнительного удовольствия я также пытаюсь решить эту проблему для вложенных словарей.

Я пытаюсь выполнить агрегацию по всем объектам, имеющим этот ключ, и суммировать значенияиз конечных узлов структуры.Например, если у меня есть следующее:

ObjectA.foo = {"a": 2, "b": 4}
ObjectB.foo = {"a": 8, "b": 16}
ObjectC.bar = {"nested": {"d": 20}}
ObjectD.bar = {"nested": {"d": 30}}

Я хочу получить выходное значение

foo.a = 10
foo.b = 20
bar.nested.d = 50

Моя первоначальная мысль - попытаться выяснить, как получить Монгочтобы сгладить ключи иерархии.Если бы я мог разбить исходные данные от объектов до серии значений ключа, где ключ представляет полный путь к значению, я мог бы легко выполнить агрегацию для этого.Однако я не уверен, как это сделать.

В идеале у меня было бы что-то вроде $ unwindKeys, но, увы, такого оператора нет.Есть $ objectToArray, который, я думаю, я мог бы затем $ unwind, но в этот момент я уже заблудился в укладке этих операторов.Это также не отвечает на проблему произвольной глубины, хотя я полагаю, что решение с одной глубиной было бы хорошим началом.

Любые идеи?

РЕДАКТИРОВАТЬ : Итак, яРешил проблему с одной глубиной, используя $ objectToArray .Вот:

db.mytable.aggregate(
  [
    {
      '$project': {
        '_id': false,
        'value': {
          '$objectToArray': '$data.input_field_with_dict'
        } 
      }
    },
    {
      '$unwind': '$value'
    },
    {
      '$group': {
        '_id': '$value.k', 
        'sum': {
          '$sum': '$value.v'
        }
      }
    }
  ]
)

Это даст вам пары ключ-значение в выбранных вами документах, которые вы затем сможете повторить.Так что в случае с моим примером выше, включающим ObjectA и ObjectB, результат вышеприведенного запроса будет:

{"_id": "a", "sum": 10}
{"_id": "b", "sum": 20}

Я до сих пор не знаю, как рекурсивно обходить структуру.Решение $ objectToArray прекрасно работает на одном известном уровне с неизвестными ключами, но у меня нет решения, если у вас есть как неизвестные ключи, так и неизвестная глубина.

Поиск продолжается: как рекурсивно суммировать илихотя бы проектировать поля с вложенными структурами и сохранять их ключевые последовательностиДругими словами, как мне сгладить структуру неизвестной глубины?Если бы я мог сгладить, я мог бы легко агрегировать по ключам в этот момент.

1 Ответ

0 голосов
/ 24 января 2019

Если ваша коллекция такая:

/* 1 */
{
    "a" : 2,
    "b" : 4
}

/* 2 */
{
    "a" : 8,
    "b" : 16
}

/* 3 */
{
    "nested" : {
        "d" : 20
    }
}

/* 4 */
{
    "nested" : {
        "d" : 30
    }
}

, то нижеприведенный запрос даст вам требуемый результат.

db.sof.aggregate([
{'$group': {
    '_id': null,
    'a': {$sum: '$a'},
    'b': {$sum: '$b'},
    'd': {$sum: '$nested.d'}
    }}
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...