Проектирование схемы заказа MongoDB

MongoDBBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы научитесь проектировать схему MongoDB для приложения электронной коммерции. Цель состоит в создании единого, комплексного документа для каждого заказа, которым легко управлять и выполнять запросы. Вы начнете с создания базовой структуры заказа, затем постепенно обогатите ее, встраивая подробную информацию о клиенте, список заказанных товаров, платежные данные и историю статусов. Этот подход демонстрирует мощь документной модели MongoDB для реальных приложений.

Создание базового документа заказа

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

Сначала откройте MongoDB Shell. Этот интерактивный интерфейс командной строки позволяет вам взаимодействовать с вашей базой данных MongoDB.

mongosh

Оказавшись в оболочке, вы увидите приглашение >. Теперь переключитесь на новую базу данных с именем ecommerce. Если база данных не существует, MongoDB создаст ее для вас при первом сохранении данных.

use ecommerce

Далее вы создадите коллекцию с именем orders, вставив в нее документ. Этот документ будет представлять собой один заказ и содержать необходимую информацию, такую как идентификатор заказа, сведения о клиенте, дату заказа и его текущий статус.

Выполните следующую команду для вставки документа:

db.orders.insertOne({
  order_id: "ORD001",
  order_date: new Date("2023-10-26T10:00:00Z"),
  customer_id: "CUST123",
  status: "pending",
  total: 150.0
});

Эта команда выполняет следующие действия:

  • db.orders: Указывает коллекцию orders в текущей базе данных.
  • insertOne(): Метод MongoDB для вставки одного документа.
  • Сам документ представляет собой объект, похожий на JSON, с парами ключ-значение для order_id, order_date, customer_id, status и total.

После успешной вставки MongoDB вернет подтверждение вместе с уникальным _id вновь созданного документа.

{
  "acknowledged": true,
  "insertedId": ObjectId("...")
}

Теперь вы создали базовую структуру для заказа. На следующем шаге вы дополните этот документ более подробной информацией.

Улучшение с помощью встроенных данных клиента

Простого customer_id часто бывает недостаточно. В реальном приложении при получении заказа вам часто потребуются имя и адрес клиента. Вместо выполнения отдельного запроса к коллекции customers мы можем встроить эту информацию непосредственно в документ заказа. Это распространенный и мощный шаблон в MongoDB, который улучшает производительность чтения.

На этом этапе вы обновите документ заказа, чтобы включить подробную, вложенную информацию о клиенте. Если вы вышли из оболочки mongosh на предыдущем шаге, пожалуйста, запустите ее снова и выполните use ecommerce.

Используйте метод updateOne(), чтобы найти документ с order_id: "ORD001" и изменить его. Оператор $set заменяет значение поля указанным значением, а $unset полностью удаляет поле.

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      customer: {
        customer_id: "CUST123",
        first_name: "John",
        last_name: "Doe",
        email: "john.doe@example.com",
        shipping_address: {
          street: "123 Main St",
          city: "Anytown",
          state: "CA",
          zip_code: "12345"
        }
      }
    },
    $unset: {
      customer_id: ""
    }
  }
);

В этой команде:

  • Первый аргумент { order_id: "ORD001" } — это фильтр для выбора документа для обновления.
  • Второй аргумент содержит операторы обновления:
    • $set: Мы устанавливаем новое поле customer, которое является вложенным документом, содержащим подробную информацию.
    • $unset: Мы удаляем старое поле customer_id верхнего уровня, чтобы избежать избыточности данных.

Чтобы проверить изменения, вы можете получить обновленный документ с помощью findOne():

db.orders.findOne({ order_id: "ORD001" });

В выводе теперь будет показан вложенный документ customer, а поле customer_id верхнего уровня будет отсутствовать. Эта вложенная структура объединяет связанные данные в одном документе.

Добавление массива позиций заказа

Заказ обычно состоит из одного или нескольких продуктов. Лучший способ смоделировать это отношение "один ко многим" в одном документе заказа — использовать массив вложенных документов. Каждый элемент массива будет представлять позицию в заказе.

Давайте обновим наш документ заказа, чтобы включить список позиций. Мы добавим поле items, которое будет массивом. Каждый объект в массиве будет содержать сведения о продукте, такие как его идентификатор, название, цена и количество.

Выполните следующую команду updateOne:

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      items: [
        {
          product_id: "PROD01",
          name: "Laptop",
          price: 1200.0,
          quantity: 1
        },
        {
          product_id: "PROD02",
          name: "Mouse",
          price: 25.0,
          quantity: 1
        }
      ],
      total: 1225.0
    }
  }
);

Здесь мы снова используем $set для добавления массива items. Мы также обновляем поле total, чтобы оно соответствовало сумме цен позиций. Хранение рассчитанной суммы непосредственно в документе является еще одной оптимизацией производительности, поскольку это избавляет от необходимости агрегации при каждом чтении.

Давайте снова проверим документ, чтобы увидеть новый массив items.

db.orders.findOne({ order_id: "ORD001" });

Вы увидите массив items, встроенный в документ заказа. Такая структура позволяет получать полный заказ, включая все его позиции, с помощью одного запроса к базе данных.

Встраивание информации об оплате

Платежные данные являются еще одной критически важной частью заказа. Подобно информации о клиенте и позициях, платежные данные могут быть встроены непосредственно в документ заказа. Это включает способ оплаты, идентификатор транзакции и статус.

На этом шаге вы добавите поддокумент payment к заказу.

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: {
      payment: {
        method: "credit_card",
        transaction_id: "TXN54321",
        status: "completed"
      }
    }
  }
);

Эта команда добавляет объект payment с тремя полями: method, transaction_id и status. Встраивание этой информации гарантирует, что все данные, связанные с одной транзакцией, находятся в одном месте.

Давайте теперь посмотрим на структуру нашего документа заказа.

db.orders.findOne({ order_id: "ORD001" });

Документ теперь содержит исчерпывающую информацию о заказе, клиенте, позициях и оплате, доступную через одну операцию чтения.

Отслеживание истории статусов заказа

Заказ проходит через различные этапы, такие как "ожидает", "обрабатывается", "отправлен" и "доставлен". В то время как поле верхнего уровня status показывает текущее состояние, часто бывает полезно вести журнал всех изменений статуса. Этого можно достичь, добавив массив status_history.

На этом заключительном этапе вы обновите статус заказа до "processing" (обрабатывается) и начнете создавать массив status_history. Оператор $push используется для добавления значения в массив.

Сначала давайте добавим начальный статус "pending" (ожидает) в историю и обновим текущий статус до "processing" (обрабатывается).

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $set: { status: "processing" },
    $push: {
      status_history: {
        status: "pending",
        timestamp: new Date("2023-10-26T10:00:00Z")
      }
    }
  }
);

Теперь давайте добавим новый статус "processing" (обрабатывается) в историю, чтобы журнал был полным.

db.orders.updateOne(
  { order_id: "ORD001" },
  {
    $push: {
      status_history: {
        status: "processing",
        timestamp: new Date("2023-10-26T11:30:00Z")
      }
    }
  }
);

Такой подход обеспечивает полный журнал жизненного цикла заказа. Вы можете запрашивать документ, чтобы в любое время просмотреть его полную историю.

db.orders.findOne({ order_id: "ORD001" });

Документ теперь включает массив status_history, предоставляя вам полное представление о пути следования заказа. Чтобы выйти из оболочки MongoDB, введите exit и нажмите Enter.

Резюме

В этой лабораторной работе вы научились проектировать практичную и эффективную схему MongoDB для заказа в интернет-магазине. Вы начали с базового документа и постепенно обогащали его, встраивая связанные данные. Вы успешно создали единый документ, который содержит сведения о клиенте, массив позиций заказа, платежную информацию и полную историю статусов. Этот паттерн встраивания документов является ключевой концепцией в проектировании схем MongoDB, которая помогает создавать производительные и масштабируемые приложения, уменьшая потребность в сложных соединениях (joins) и множественных запросах.