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

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

> db.data.find()
{ "_id" : "foo1", "1" : { "bar" : 6 }, "0" : { "bar" : 11 }, "3" : { "bar" : 8 }, "2" : { "bar" : 0 }, "5" : { "bar" : 8 }, "4" : { "bar" : 19 }, "6" : { "bar" : 8 } }
{ "_id" : "foo2", "1" : { "bar" : 18 }, "0" : { "bar" : 3 }, "3" : { "bar" : 19 }, "2" : { "bar" : 0 }, "5" : { "bar" : 13 }, "4" : { "bar" : 17 }, "7" : { "bar" : 8 }, "6" : { "bar" : 8 }, "8" : { "bar" : 8 } }
{ "_id" : "foo3", "1" : { "bar" : 0 }, "0" : { "bar" : 2 }, "3" : { "bar" : 18 }, "2" : { "bar" : 2 }, "4" : { "bar" : 12 } }

Я могу сделать это индивидуально, но возможно ли это сделать это по всему набору данных? Формат вывода мне не очень важен, но вот идея:

Желаемый результат:

bar0: 16
bar1: 24
bar2: 2
bar3: 45
bar4: 48
bar5: 21
bar6: 16
bar7: 8
bar8: 8

1 Ответ

2 голосов
/ 27 апреля 2020

Вы можете сделать это, используя агрегацию MongoDB framework:

db.collection.aggregate([
    /** Remove not needed fields, which will lessen size of doc */
    { $project: { _id: 0 } },
    /** As you've dynamic field names - convert each field in doc into {k:...,v:...} & entire doc is pushed into array field `data` */
    {
      $project: { data: {  $objectToArray: "$$ROOT" } }
    },
    {
      $unwind: "$data"
    },
    /** group to bring same 'k' values together & sum-up bar value */
    {
      $group: { _id: "$data.k", bar: { $sum: "$data.v.bar" } }
    },
    /** Can be Optional, Project needed fields `data` will be an object */
    {
      $project: {
        _id: 0,
        data: { $arrayToObject: [ [ { "k": { $concat: [ "bar", "$_id" ] }, "v": "$bar" } ] ] } } 
    },
    /** Make `data` field as new root for doc */
    {
      $replaceRoot: {
        newRoot: "$data"
      }
    }
  ])

Тест: mongoplayground

Примечание: Старайтесь не иметь динамических c имен ключей - что приведет к множеству проблем при чтении. Также этапы после $group являются необязательными в приведенном выше запросе, они там для того, чтобы вывод был похож в желаемом формате лучше тестировать до стадии $group и проверить, подходит ли она вам.

...