Как использовать агрегирование и группирование по двум полям

#mongodb #mongoose

#mongodb #мангуст

Вопрос:

Я пытаюсь использовать агрегированную группу и сопоставление для получения моих данных.

Это мой код:

   itemShell.aggregate(
      [
        {
          $match: { shell_id_in_whareHouse: {$in:shelfIds}}
        },
        {
          $group: {
            _id: "$item",
            position:{'$last':'$position'},
            total: { $sum: "$amount" }
          }
        }
      ],
      function(err, results) {
        if (err) console.log(err)
        else {
          res.json(results);
        }
      }
    );
 

Вот как выглядят объекты itemShell:

 {item:1313,position:'2A',amount:500},
{item:1313,position:'2A',amount:200},
{item:1414,position:'1A',amount:500},
{item:1414,position:'2A',amount:800},
{item:1313,position:'1A',amount:300}
 

Моя проблема в том, что результат results таков: (из-за $ Последнего аккумулятора)

 [
{_id:1313,position:'1A',total:1000},
{_id:1414,position:'2A',total:1300},
]
 

Мой желаемый результат должен быть:

 [
    {_id:1313,position:'2A',total:700},
    {_id:1414,position:'1A',total:500},
    {_id:1414,position:'2A',total:800},
    {_id:1313,position:'1A',total:300}
]
 

Таким образом, он будет группировать только те объекты, у которых номер элемента и строка позиции совпадают.

есть предложения?

Ответ №1:

Вы на правильном пути, вам нужно сгруппировать по двум полям, используя $group stage with _id в качестве объекта, как показано ниже:

 ItemShell.aggregate([
  {
    $match: {}
  },
  {
    $group: {
      _id: { item: '$item', position: '$position' },
      total: { $sum: '$amount' }
    }
  },
  {
    $project: {
      _id: 0,
      item: '$_id.item',
      position: '$_id.position',
      total: 1
    }
  }
]);
 

Вывод

 [
  {
    "item": 1313,
    "position": "1A",
    "total": 300
  },
  {
    "item": 1313,
    "position": "2A",
    "total": 700
  },
  {
    "item": 1414,
    "position": "2A",
    "total": 800
  },
  {
    "item": 1414,
    "position": "1A",
    "total": 500
  }
]
 

Вот игровая площадка для монго: https://mongoplayground.net/p/Ne5h9WkzjEm

Ответ №2:

Я думаю, это должно сработать

 itemShell.aggregate([
    {
    "$group": {
      "_id": {
        "item": "$item",
        "positon": "$positon"
      },
      "items": {
        "$first": "$ROOT"
      },
      "amount": {
        "$sum": "$amount"
      }
    }
  },
  {
    "$project": {
      "item": "$items.item",
      "positon": "$items.position",
      "amount": 1,
      "_id": "$items._id"
    }
  }
    ],
      function(err, results) {
        if (err) console.log(err)
        else {
          res.json(results);
        }
      }
    );
 

Вы можете увидеть результаты здесь: https://mongoplayground.net/p/h7aa_so1Cok

Вывод:

 [
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "amount": 1000,
    "item": 1313,
    "positon": "2A"
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "amount": 1300,
    "item": 1414,
    "positon": "1A"
  }
]