Мангуст агрегирует и суммирует вложенные поля OBJECT (NOT ARRAY) - PullRequest
1 голос
/ 26 сентября 2019

Я видел много сообщений об использовании aggregate в sum вложенных ARRAY полей, я пытался использовать его со своим вложенным объектом, который не работал.

Когда я запрашиваю, структура данных выглядит примерно так ...

[
        {
            "key": "value",
            "more_key": "more_value",
            "meals": {
                "A": {
                    "name": "salmon",
                    "amount": "8"
                },
                "B": {
                    "name": "vege",
                    "amount": "6"
                },
            }
        },
        {
            "key": "value",
            "more_key": "more_value",
            "meals": {
                "A": {
                    "name": "salmon",
                    "amount": "8"
                },
                "B": {
                    "name": "vege",
                    "amount": "6"
                },
                "C": {
                    "name": "other meal",
                    "amount": "6"
                },
            }
        },
    ];

Я пытаюсь суммировать amount

Я пробовал что-то подобное...

await Model.aggregate([
        { $match: { isDeleted: false } },
        { $unwind: '$meals' },  // tried with + without this
        { $group: { _id: null, sum: { $sumA: '$meals.A.amount', $sumB: '$meals.B.amount' } } }
    ]);

Может кто-нибудь дать мне какой-нибудь совет и совет, как это можно сделать?

Заранее спасибо.

1 Ответ

2 голосов
/ 26 сентября 2019

Здесь происходит несколько вещей:

1) $unwind не работает с объектами, только с массивами.Вы можете исправить это, преобразовав объект питания в массив с $objectToArray

2) Ваше поле суммы выглядит так, как будто оно имеет тип String, поэтому его необходимо преобразовать в число для суммирования

Вот агрегация, которая делает то, что вам нужно:

await Model.aggregate([
  // Convert meals object to array
  { $project: { meals: { $objectToArray: '$meals' }}},

  //  unwind meals array
  { $unwind:  '$meals' },

  // convert meals.v.amount to integer and sum them (the v is shorthand for values)
  { $group: { 
    _id: null, 
    total: {
      $sum: { 
        $convert: {
          input: '$meals.v.amount',
          to: 'int'
        }
      }
    }
  }}
])

Вы можете изменить _id из $ group на _id: meals.k, чтобы суммировать по ключам объекта питания, то есть A, B, C

...