Группировка по полю при получении последнего документа для каждого поля с MongoDB - PullRequest
1 голос
/ 21 марта 2020

Проблема

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

[
  { $sort: { date: 1 } },
  {
    $group: {
      _id: '$userId',
      stocks: { $last: '$stocks' },
    },
  },
  { $unwind: '$stocks' },
  {
    $group: {
      _id: '$stocks.productId',
      totalQuantity: { $sum: '$stocks.quantity' },
      stocks: { $push: { userId: '$_id', quantity: '$stocks.quantity' } },
    },
  },
]

Теперь, возможно, запись о запасе не содержит все заполненные продукты. Так что я застрял при написании нового агрегата.

В основном мне нужно сгруппировать все продукты по productId и получить массив последней записи для каждого пользователя.

Вывод

Это мой ожидаемый результат:

[
  {
    "_id": ObjectId("5e75eae1359fc8159d5b6073"),
    "totalQuantity": 33,
    "stocks": [
      {
        "userId": ObjectId("5e75f498359fc8159d5b6075"),
        "lastDate": "2020-03-21T11:45:53.077Z",
        "quantity": 33
      }
    ]
  },
  {
    "_id": ObjectId("5e75eaea359fc8159d5b6074"),
    "totalQuantity": 2,
    "stocks": [
      {
        "userId": ObjectId("5e75f498359fc8159d5b6075"),
        "lastDate": "2020-03-21T11:45:53.077Z",
        "quantity": 2
      }
    ]
  } 
]

Документы

Документы (при полном заполнении):

{
  "_id": ObjectId("5e75fe71e4a3e0323ba47e0a"),
  "date": "2020-03-21T11:45:53.077Z",
  "userId": ObjectId("5e75f498359fc8159d5b6075"),
  "stocks": [
    {
      "productId": ObjectId("5e75eae1359fc8159d5b6073"),
      "quantity": 33
    },
    {
      "productId": ObjectId("5e75eaea359fc8159d5b6074"),
      "quantity": 2
    }
  ]
}

Иногда он не заполняется для Весь инвентарь (вот почему мне нужно lastDate):

{
  "_id": ObjectId("5e75fe71e4a3e0323ba47e0a"),
  "date": "2020-03-21T11:45:53.077Z",
  "userId": ObjectId("5e75f498359fc8159d5b6075"),
  "stocks": [
    {
      "productId": ObjectId("5e75eae1359fc8159d5b6073"),
      "quantity": 33
    }
  ]
}

1 Ответ

0 голосов
/ 21 марта 2020

Попробуйте это:

db.collection.aggregate([
  {
    $group: {
      _id: "$userId",
      root: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $addFields: {
      root: {
        $map: {
          input: "$root",
          as: "data",
          in: {
            "stocks": {
              $map: {
                input: "$$data.stocks",
                as: "stock",
                in: {
                  "productId": "$$stock.productId",
                  "userId": "$$data.userId",
                  "quantity": "$$stock.quantity",
                  "lastDate": "$$data.date"
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $unwind: "$root"
  },
  {
    $replaceRoot: {
      newRoot: "$root"
    }
  },
  {
    $unwind: "$stocks"
  },
  {
    $sort: {
      "stocks.lastDate": 1
    }
  },
  {
    $group: {
      _id: "$stocks.productId",
      totalQuantity: {
        $last: "$stocks.quantity"
      },
      stocks: {
        $last: "$stocks"
      }
    }
  },
  {
    $addFields: {
      stocks: [
        {
          "lastDate": "$stocks.lastDate",
          "quantity": "$stocks.quantity",
          "userId": "$stocks.userId"
        }
      ]
    }
  }
])

MongoPlayground

...