Группировка из нескольких массивов и поиск суммы

#mongodb #mongodb-query #aggregation-framework

Вопрос:

У меня есть эти документы.

 [
    {
        _id: 'a1',
        sales: [
            {
                amont: 12,
                servicer_id: 'A',
            },
            {
                amont: 10,
                servicer_id: 'B',
            },
        ],
        service: [
            {
                amont: 25,
                servicer_id: 'A',
            },
            {
                amont: 20,
                servicer_id: 'B',
            },
        ],
    },
    {
        _id: 'a2',
        sales: [
            {
                amont: 10,
                servicer_id: 'A',
            },
            {
                amont: 20,
                servicer_id: 'B',
            },
        ],
        service: [
            {
                amont: 15,
                servicer_id: 'A',
            },
            {
                amont: 10,
                servicer_id: 'B',
            },
        ],
    },
]
 

Из приведенного выше документа я хочу найти следующее.

1.Номер услуги, оказанной как обслуживающим лицом A, так и B.

2.Количество продаж, совершенных как поставщиком услуг A, так и B.

3.Общий объем услуг обслуживающего лица A и B.

4.Общий объем продаж услуг A и B.

Ожидаемые результаты

 [
    {
        servicer: 'A',
        services: 2,
        sales: 2,
        totalSale: 22,
        totalService: 40,
    },
    {
        servicer: 'B',
        services: 2,
        sales: 2,
        totalSale: 30,
        totalService: 30,
    },
];  
 

Ответ №1:

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

 db.collection.aggregate([
  {
    $unwind: {
      path: "$service",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $group: {
      _id: {
        serviceId: "$service.servicer_id",
        docId: "$_id"
      },
      services: {
        $sum: 1
      },
      sales: {
        $first: "$sales"
      },
      totalService: {
        $sum: "$service.amont"
      },
      
    }
  },
  {
    "$addFields": {
      serviceSales: {
        $filter: {
          input: "$sales",
          as: "sale",
          cond: {
            $eq: [
              "$sale.servicer_id",
              "$_id.serviceId"
            ]
          }
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id.serviceId",
      services: {
        $sum: "$services"
      },
      sales: {
        $sum: {
          $size: "$serviceSales"
        }
      },
      totalService: {
        $sum: "$totalService"
      },
      totalSale: {
        $sum: {
          $reduce: {
            input: "$serviceSales",
            initialValue: 0,
            in: {
              $sum: [
                "$value",
                "$this.amont"
              ]
            }
          }
        }
      }
    }
  }
])
 

Игровая площадка Монго

Комментарии:

1. Я проверил приведенный выше ответ. Но я получил неверную сумму, когда добавил еще один объект в массив услуг. для большего mongoplayground.net/p/5pNK2gA6lwL @Том Слабберт

2. в какой именно области проблема? один из $sum операторов, вероятно, не соответствует нужной вам логике.

3. Не могли бы вы, пожалуйста, проверить ссылку mongoplayground.net/p/5pNK2gA6lwL . Номер продажи неверен для сервисера B. На самом деле у сервисера А всего 2 продажи. Эта ошибка возникает, когда я добавляю еще один объект в массив servicer

4. Хорошо, похоже, я неправильно понял вопрос, вот исправление, которое должно сработать: mongoplayground.net/p/j_JP1O52mFZ я также отредактирую свой ответ. обратите внимание, что это делается в предположении, что не может быть продажи услуги без того, чтобы эта услуга не находилась в том же массиве.