Агрегация MongoDB для группировки нескольких уровней динамических c ключей - PullRequest
0 голосов
/ 01 мая 2020

это продолжение другого вопроса ( агрегирование MongoDB для динамических групп c ключей ) - с этим я решил одну из нескольких проблем и надеялся, что у меня будет путь к решению следующей проблема. Раньше был только один документ с именем Dynami c - теперь у меня есть два вложенных документа с именами Dynami c. Я настроил образец для представления данных, которые выглядят следующим образом:

{ "_id" : "foo1", "baz" : { "data" : { "1" : { "i" : { "bork" : 5 }, "s" : { "bork" : 5 }, "bar" : 18, "d" : { "bork" : 4 }, "g" : { "bork" : 2 }, "y" : { "bork" : 5 }, "x" : { "bork" : 5 }, "z" : { "bork" : 5 }, "e" : { "bork" : 2 } }, "0" : { "b" : { "bork" : 5 }, "bar" : 10, "d" : { "bork" : 5 }, "k" : { "bork" : 1 }, "m" : { "bork" : 3 }, "l" : { "bork" : 3 }, "r" : { "bork" : 1 }, "u" : { "bork" : 4 }, "t" : { "bork" : 5 }, "y" : { "bork" : 3 }, "x" : { "bork" : 1 } }, "3" : { "k" : { "bork" : 3 }, "bar" : 15 }, "2" : { "u" : { "bork" : 3 }, "r" : { "bork" : 1 }, "bar" : 4, "e" : { "bork" : 3 }, "h" : { "bork" : 4 } }, "5" : { "q" : { "bork" : 5 }, "k" : { "bork" : 5 }, "bar" : 18 }, "4" : { "a" : { "bork" : 5 }, "b" : { "bork" : 4 }, "bar" : 6, "d" : { "bork" : 3 }, "h" : { "bork" : 5 }, "z" : { "bork" : 2 }, "l" : { "bork" : 4 } } } } }
{ "_id" : "foo2", "baz" : { "data" : { "1" : { "bar" : 0, "j" : { "bork" : 3 }, "l" : { "bork" : 3 }, "n" : { "bork" : 2 }, "q" : { "bork" : 3 }, "p" : { "bork" : 1 }, "r" : { "bork" : 1 }, "w" : { "bork" : 4 }, "v" : { "bork" : 2 }, "e" : { "bork" : 3 }, "z" : { "bork" : 2 } }, "0" : { "a" : { "bork" : 5 }, "b" : { "bork" : 1 }, "bar" : 17, "g" : { "bork" : 3 }, "i" : { "bork" : 4 }, "k" : { "bork" : 1 }, "j" : { "bork" : 1 }, "o" : { "bork" : 5 }, "q" : { "bork" : 3 }, "r" : { "bork" : 4 }, "t" : { "bork" : 3 } }, "3" : { "r" : { "bork" : 5 }, "z" : { "bork" : 2 }, "bar" : 10, "v" : { "bork" : 3 } }, "2" : { "p" : { "bork" : 2 }, "bar" : 18, "d" : { "bork" : 3 }, "g" : { "bork" : 4 }, "v" : { "bork" : 5 }, "i" : { "bork" : 2 }, "h" : { "bork" : 1 }, "z" : { "bork" : 2 }, "m" : { "bork" : 3 } } } } }
{ "_id" : "foo3", "baz" : { "data" : { "1" : { "q" : { "bork" : 2 }, "s" : { "bork" : 4 }, "b" : { "bork" : 2 }, "bar" : 0, "v" : { "bork" : 2 }, "i" : { "bork" : 2 }, "k" : { "bork" : 3 }, "l" : { "bork" : 1 }, "n" : { "bork" : 5 } }, "0" : { "q" : { "bork" : 5 }, "c" : { "bork" : 4 }, "e" : { "bork" : 2 }, "f" : { "bork" : 2 }, "bar" : 3, "m" : { "bork" : 2 }, "l" : { "bork" : 3 } }, "3" : { "a" : { "bork" : 2 }, "g" : { "bork" : 4 }, "c" : { "bork" : 4 }, "bar" : 18, "t" : { "bork" : 1 }, "w" : { "bork" : 2 }, "p" : { "bork" : 5 }, "e" : { "bork" : 2 }, "l" : { "bork" : 2 } }, "2" : { "e" : { "bork" : 5 }, "k" : { "bork" : 5 }, "bar" : 10, "l" : { "bork" : 2 } }, "5" : { "m" : { "bork" : 2 }, "j" : { "bork" : 1 }, "bar" : 9 }, "4" : { "bar" : 13, "w" : { "bork" : 4 }, "v" : { "bork" : 3 }, "i" : { "bork" : 2 }, "k" : { "bork" : 5 }, "m" : { "bork" : 1 }, "n" : { "bork" : 3 } }, "7" : { "x" : { "bork" : 1 }, "bar" : 13 }, "6" : { "j" : { "bork" : 3 }, "bar" : 19, "d" : { "bork" : 2 }, "w" : { "bork" : 4 }, "f" : { "bork" : 1 }, "x" : { "bork" : 1 }, "z" : { "bork" : 3 }, "m" : { "bork" : 4 }, "t" : { "bork" : 2 } } } } }

Как и прежде, я группирую по значению baz.data.NAbork и пытаюсь вернуть счет каждого из тех.

Моей первой мыслью было следовать тому же методу, что и раньше, дважды -

> db.data.aggregate([ 
  { $project: { _id:0, "baz.data":1} }, 
  { $project: { data: { $objectToArray: "$baz.data" } } }, 
  { $unwind: "$data" }, 
  { $project: { borkTree: { $objectToArray: "$data.v" } } }, 
  { $unwind: "$borkTree" }, 
  { $group: { _id: "$borkTree.v.bork", channel: {$first:"$borkTree.v.bork"}, count: { $sum:1 } } } 
])

Это возвращает это:

{ "_id" : 4, "channel" : 4, "count" : 16 }
{ "_id" : 1, "channel" : 1, "count" : 17 }
{ "_id" : 3, "channel" : 3, "count" : 23 }
{ "_id" : null, "channel" : null, "count" : 18 }
{ "_id" : 5, "channel" : 5, "count" : 22 }
{ "_id" : 2, "channel" : 2, "count" : 26 }

Почему я получаю "ноль" результат для _id? Кроме того, это кажется неэффективным, есть ли способ сделать это за один проход вместо двух?

[ПРАВИТЬ] Я не думал, что нулевое значение будет проблемой, но когда я пытаюсь очистить вывод / преобразование обратно в объект, нулевое значение которого вызывает ошибку агрегирования:

{ $project: { _id: 0, data: { $arrayToObject: [ [ { "k": { $concat: [ "bork", { $toString: "$channel" } ] }, "v": "$count" } ] ] } } }, { $replaceRoot: { newRoot: "$data" } } ])

2020-05-01T07:38:04.267-0500 E  QUERY    [js] Error: command failed: {
    "ok" : 0,
    "errmsg" : "$arrayToObject requires an object with keys 'k' and 'v', where the value of 'k' must be of type string. Found type: null",
} : aggregate failed :
...