← Назад к курсу

Подробное пособие по работе с MongoDB в Python

1. Что такое MongoDB?

MongoDB — документоориентированная NoSQL-база данных, которая хранит данные в формате BSON (бинарный JSON).

  • Документ: Основная единица данных (аналог строки в SQL). Пример:
    {
      "_id": ObjectId("5f9d9a3d7e4a3d2a8c0e1b2c"),
      "name": "Анна",
      "age": 28,
      "address": {"city": "Москва", "street": "Тверская"}
    }
    
  • Коллекция: Группа документов (аналог таблицы в SQL).
  • Гибкая схема: Документы в одной коллекции могут иметь разную структуру.

2. Ключевые особенности

Параметр Описание
Горизонтальное масштабирование Автоматическое шардирование распределяет данные по серверам.
Высокая производительность Оптимизирована для операций записи/чтения.
Мощный язык запросов Поддерживает фильтрацию, сортировку, агрегацию, геопоиск.
Репликация Автоматическое копирование данных для отказоустойчивости.

3. Установка и настройка

  1. Установите MongoDB:
  2. Запустите сервер:
    mongod  # Linux/Mac
    
  3. Установите драйвер Python:
    pip install pymongo
    

4. CRUD-операции (с примерами)

Подключение к БД

from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")  # Подключение
db = client["shop_db"]  # Создание БД (если не существует)
products = db.products  # Создание коллекции

Create (Вставка)

# Вставка одного документа
product = {
    "name": "Ноутбук",
    "price": 899.99,
    "stock": 100,
    "tags": ["электроника", "техника"]
}
result = products.insert_one(product)
print("ID нового документа:", result.inserted_id)

# Вставка нескольких документов
new_products = [
    {"name": "Смартфон", "price": 599.99, "stock": 200},
    {"name": "Наушники", "price": 149.99, "stock": 50}
]
result = products.insert_many(new_products)
print("ID новых документов:", result.inserted_ids)

Read (Чтение)

# Поиск одного документа
item = products.find_one({"name": "Ноутбук"})
print(item)

# Поиск всех документов с фильтром
for product in products.find({"price": {"$lt": 600}}):  # Цена < 600
    print(product["name"])

# Проекция (выбор полей)
print(products.find_one({}, {"name": 1, "price": 1}))  # Только name и price

Update (Обновление)

# Обновление одного документа
products.update_one(
    {"name": "Наушники"},
    {"$set": {"price": 129.99}}  # Оператор $set
)

# Обновление нескольких документов
products.update_many(
    {"stock": {"$lt": 150}}, 
    {"$set": {"discount": True}}
)

# Инкремент значения ($inc)
products.update_one({"name": "Смартфон"}, {"$inc": {"stock": 10}})

Delete (Удаление)

# Удаление одного документа
products.delete_one({"name": "Ноутбук"})

# Удаление нескольких документов
products.delete_many({"stock": {"$lte": 50}})

5. Индексы и производительность

Индексы ускоряют поиск и сортировку. Без индексов MongoDB выполняет collection scan (перебор всех документов).

# Создание индекса
products.create_index("name")  # Простой индекс
products.create_index([("price", 1)])  # Сортировка по возрастанию цены

# Составной индекс
products.create_index([("stock", 1), ("price", -1)])

# Удаление индекса
products.drop_index("name_1")

6. Агрегации

Агрегации — аналог SQL GROUP BY. Пример: подсчет среднего цены по категориям.

pipeline = [
    {"$group": {"_id": "$category", "avg_price": {"$avg": "$price"}}},
    {"$sort": {"avg_price": -1}}
]
results = products.aggregate(pipeline)
for res in results:
    print(f"Категория: {res['_id']}, Средняя цена: {res['avg_price']:.2f}")

7. Демо-приложение: Интернет-магазин

from pymongo import MongoClient
from bson.objectid import ObjectId

client = MongoClient("mongodb://localhost:27017/")
db = client.online_store
products = db.products

def add_product():
    name = input("\nНазвание товара: ")
    price = float(input("Цена: "))
    category = input("Категория: ")
    products.insert_one({"name": name, "price": price, "category": category})
    print(f"✅ Товар '{name}' добавлен!")

def show_products():
    print("\n=== ТОВАРЫ ===")
    for prod in products.find():
        print(f"{prod['_id']} | {prod['name']} - {prod['price']} руб.")
    print("===============")

def apply_discount():
    category = input("Категория для скидки: ")
    discount = float(input("Размер скидки (%): "))
    products.update_many(
        {"category": category},
        {"$mul": {"price": 1 - discount/100}}  # Умножаем цену на коэффициент
    )
    print(f"✅ Скидка {discount}% применена к категории '{category}'")

def main():
    while True:
        print("\n1. Добавить товар\n2. Показать товары\n3. Сделать скидку\n4. Выход")
        choice = input("Выберите действие: ")
        if choice == "1": add_product()
        elif choice == "2": show_products()
        elif choice == "3": apply_discount()
        elif choice == "4": break
        else: print("Ошибка ввода!")

if __name__ == "__main__":
    main()

8. Когда использовать MongoDB?

Идеальные сценарии:

  • Каталоги продуктов с динамическими атрибутами
  • Контент-менеджмент системы (CMS)
  • Логирование данных приложений
  • Пользовательские профили с разной структурой

Не подходит:

  • Для финансовых транзакций (требуется ACID)
  • Систем, где критичны JOIN между таблицами

9. Лучшие практики

  1. Валидация схемы:
    db.create_collection("products", validator={
        "$jsonSchema": {
            "bsonType": "object",
            "required": ["name", "price"],
            "properties": {
                "price": {"bsonType": "double", "minimum": 0}
            }
        }
    })
    
  2. Обработка ошибок:
    from pymongo.errors import DuplicateKeyError
    try:
        products.insert_one({"name": "Ноутбук"})
    except DuplicateKeyError:
        print("Товар уже существует!")
    
  3. Оптимизация запросов:
    • Всегда используйте проекции ({"_id": 0, "name": 1}).
    • Избегайте $where (медленные JavaScript-запросы).

Документация: MongoDB Manual, PyMongo Tutorial