Урок 84. MongoDB и Python. Модули

📁 Блок: Базы данных и модули ⏱️ Время изучения: ~90 мин 🎯 Сложность: Средняя
#close #find #sort #list #in #import #from

⚡ Кратко: что меняется

  • SQL: таблицы, строки, фиксированная схема, JOIN-запросы. NoSQL (MongoDB): документы, словари, гибкая схема, вложенные данные.
  • Старый подход: один большой скрипт, где всё смешано — подключение, логика и вывод.
  • Новый подход: код разбит на модули: подключение, бизнес-логика, запуск. Используй if __name__ == "__main__".

⚖️ SQL vs NoSQL: разный подход к данным

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

SQL-мышление

# Реляционный подход: две таблицы и JOIN
SELECT p.name, c.name
FROM products p
JOIN categories c ON p.category_id = c.id
WHERE p.price < 5

Недостатки:

  • Нужно заранее проектировать схему.
  • Изменение структуры требует миграций.
  • Сложные связи делают запросы громоздкими.

NoSQL-мышление

# MongoDB: документ содержит все нужные поля
for doc in products.find({"price": {"$lt": 5}}):
    print(doc["name"], doc.get("category"))

Преимущества:

  • Нет жёсткой схемы — документы могут иметь разные поля.
  • Запросы ближе к структурам данных Python.
  • Легко добавлять новые поля без миграций.
⚠️ Проверить по документации: MongoDB поддерживает агрегации и ссылки между коллекциями через DBRef и $lookup. Для сложных отношений иногда всё же используют нормализацию данных, как в SQL.

📜 Монолитный скрипт vs модульный код

Когда программа маленькая, удобно держать всё в одном файле. Но по мере роста проекта код становится сложно читать и поддерживать.

Старый подход: всё в одном файле

from pymongo import MongoClient

client = MongoClient("mongodb://...")
db = client["ich_edit"]
products = db["products"]

product = {"name": "Notebook", "price": 5.99, "stock": 120}
products.insert_one(product)

for doc in products.find():
    print(doc)

client.close()

Недостатки:

  • Подключение к базе смешано с бизнес-логикой.
  • Код нельзя переиспользовать в других скриптах.
  • Секреты (логин, пароль) хранятся прямо в основном файле.

Новый подход: разделение на модули

Файл: db.py

from pymongo import MongoClient

MONGO_URI = "mongodb://..."


def get_collection(name):
    client = MongoClient(MONGO_URI)
    return client["ich_edit"][name]

Файл: products_service.py

from db import get_collection


def add_product(name, price, stock):
    products = get_collection("products")
    result = products.insert_one({
        "name": name,
        "price": price,
        "stock": stock,
    })
    return result.inserted_id


def list_products():
    products = get_collection("products")
    return list(products.find())

Файл: main.py

from products_service import add_product, list_products

if __name__ == "__main__":
    add_product("Notebook", 5.99, 120)
    for product in list_products():
        print(product)

Преимущества:

  • Каждый модуль отвечает за одну задачу.
  • Логику легко тестировать и переиспользовать.
  • Точка входа в программу отделена от реализации.

📊 Сравнение в таблице

АспектСтарый подходНовый подход
Структура данныхТаблицы и строки (SQL)Документы и словари (NoSQL)
СхемаФиксированнаяГибкая
Организация кодаОдин большой скриптНесколько модулей и пакетов
Повторное использованиеСложноЛегко через import
ТестированиеСложно изолировать частиМожно тестировать модули отдельно
Точка входаКод выполняется при импортеКод выполняется только под if __name__ == "__main__"
⚠️ Проверить по документации: в production-проектах для управления конфигурацией и секретами используют переменные окружения, файлы .env и библиотеки вроде pydantic-settings. Выбор между SQL и NoSQL зависит от задачи: для сложных транзакций часто выбирают SQL, для гибких схем — NoSQL.