Как группировать документы по определенному полю в MongoDB

#mongodb #mongodb-query #aggregation-framework #pymongo

#mongodb #mongodb-запрос #агрегация-фреймворк #pymongo

Вопрос:

В настоящее время у меня есть коллекция book_orders, которая выглядит следующим образом:

 {
    "order_id" : 1,
    "customer_name": "Nikos",
    "order_type": "digital",
    "title": "Zorba",
    "price": 25
}
{
    "order_id" : 2,
    "customer_id": "Giorgos",
    "order_type": "physical_delivery",
    "title": "War and Peace",
    "price": 30
}
{
    "order_id" : 2,
    "customer_id": "Giorgos",
    "order_type": "digital",
    "title": "Children of the Gabalawi Street",
    "price": 35
}
{
    "order_id" : 3,
    "customer_id": "Giorgos",
    "order_type": "digital",
    "title": "The Desert of the Tartars",
    "price": 40
}
  

Что я хочу сделать с этой коллекцией, так это то, что я хочу получить такой результат, где я группирую заказы по order_id и вставляю их в списки с именем digital_orders и physical_orders последующей группировкой по order_type .

Я предполагаю, что мне нужно будет использовать агрегацию, но я не уверен, как это сделать. Важно, чтобы я мог сохранять такие поля, как customer_name , title , и price . Любая помощь приветствуется.

 {
  "order_id": 1,
  "customer_name": "Nikos",
  "digital_orders": [
    {
      "title": "Zorba",
      "price": 25
    }
  ],
  "physical_orders": []
},
{
  "order_id": 2,
  "customer_name": "Giorgos",
  "digital_orders": [
    {
      "title": "War and Peace",
      "total": 25
    }
  ],
  "physical_orders": [
    {
      "title": "Children of the Gabalawi Street",
      "price": 35
    }
  ]
},
{
  "order_id": 3,
  "customer_name": "Giorgos",
  "digital_orders": [],
  "physical_orders": [
    {
      "title": "The Desert of the Tartars",
      "total": 40
    }
  ]
}
  

Ответ №1:

Вы можете попробовать,

  • $group сначала order_id customer_name и получите все заказы с обязательными полями в массиве
  • $project чтобы отобразить обязательные поля, создайте 2 поля: одно digital_orders для фильтрации цифровых заказов из массива заказов, а второе physical_orders — для фильтрации физических заказов из массива заказов
 db.collection.aggregate([
  {
    $group: {
      _id: "$order_id",
      customer_name: { $first: "$customer_name" },
      orders: {
        $push: {
          title: "$title",
          price: "$price",
          order_type: "$order_type"
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      order_id: "$_id",
      customer_name: 1,
      digital_orders: {
        $filter: {
          input: "$orders",
          cond: { $eq: ["$$this.order_type", "digital"] }
        }
      },
      physical_orders: {
        $filter: {
          input: "$orders",
          cond: { $eq: ["$$this.order_type", "physical_delivery"] }
        }
      }
    }
  }
])
  

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

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

1. Спасибо, это помогло. Если бы я хотел отсортировать заказы внутри physical_orders и digital orders по цене внутри $push , как бы я это сделал?

2. Вы можете использовать этап $sort на первом этапе, посмотрите эту игровую площадку