Начало работы с MongoDB
Установите MongoDB, подключитесь через PyMongo и выполните базовые CRUD-операции в Python на понятных рабочих примерах.
В этой главе рассматривается MongoDB и показывается, как использовать её из Python с помощью драйвера PyMongo. К концу главы у вас будет установлена MongoDB, настроено рабочее подключение, и вы получите чёткое представление о том, как вставлять, запрашивать, обновлять и удалять документы.
Что такое MongoDB?
MongoDB — это документная база данных — разновидность NoSQL-базы данных, которая хранит записи в виде JSON-подобных документов вместо строк и столбцов. Каждый документ является самостоятельным объектом, который может содержать вложенные поля и массивы, что делает его естественным выбором для данных, которые не вписываются в фиксированную схему.
Ключевые характеристики:
- Гибкая схема. Два документа в одной коллекции могут иметь совершенно разные поля.
- Богатый язык запросов. Фильтрация, проекция, сортировка, ограничение и агрегация выполняются одним вызовом драйвера.
- Горизонтальная масштабируемость. Встроенное шардирование и наборы реплик обеспечивают работу с большими объёмами данных и высокую доступность.
- Нативный JSON. Документы хранятся в формате BSON (Binary JSON), поэтому словари Python напрямую отображаются в документы MongoDB.
Когда выбрать MongoDB вместо реляционной базы данных
| Ситуация | Подходит? |
|---|---|
| Быстро меняющаяся структура данных (прототипы, API) | Да |
| Иерархические / вложенные данные | Да |
Сложные запросы с JOIN по нескольким таблицам | Предпочтительнее SQL |
Строгие ACID-транзакции по многим таблицам | Предпочтительнее SQL |
| Полнотекстовый поиск в больших масштабах | Сочетайте с Elasticsearch |
Установка MongoDB
Вариант 1 — Локальная установка
Скачайте MongoDB Community Server с сайта mongodb.com/try/download/community, выберите свою операционную систему и следуйте инструкциям установщика. Затем запустите сервер:
# macOS / Linux
mongod --dbpath /data/db
# Windows (PowerShell, run as Administrator)
mongod --dbpath "C:\data\db"Убедитесь, что MongoDB запущена, открыв второй терминал и выполнив:
mongosh --eval "db.adminCommand('ping')"Ожидаемый вывод:
{ ok: 1 }Вариант 2 — Docker (быстрейший способ для разработки)
Если у вас установлен Docker, можно полностью обойтись без локальной установки:
docker run -d --name mongo -p 27017:27017 mongo:7Это загружает официальный образ MongoDB 7 и открывает порт 27017 на вашем компьютере. Остановить контейнер можно командой docker stop mongo.
Вариант 3 — MongoDB Atlas (облако)
Atlas — полностью управляемый облачный сервис MongoDB с бесплатным тарифом. После регистрации скопируйте строку подключения из панели управления — она выглядит примерно так:
mongodb+srv://username:[email protected]/Этот URI можно использовать везде, где в данной главе встречается mongodb://localhost:27017/.
Установка драйвера PyMongo
PyMongo — официальный драйвер Python для MongoDB. Установите его с помощью pip:
pip install pymongoДля работы с MongoDB Atlas дополнительно установите пакет с DNS-резолвером:
pip install "pymongo[srv]"Проверьте установку:
import pymongo
print(pymongo.version)
# e.g. 4.7.3Подключение к MongoDB
MongoClient — точка входа для всех операций драйвера. Создайте один клиент на приложение и переиспользуйте его — клиент управляет внутренним пулом соединений.
from pymongo import MongoClient
# Local server with default host and port
client = MongoClient("mongodb://localhost:27017/")
# Verify connectivity (raises ConnectionFailure if the server is unreachable)
client.admin.command("ping")
print("Connected successfully")В продакшен-коде всегда явно обрабатывайте ошибки подключения:
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
client = MongoClient("mongodb://localhost:27017/", serverSelectionTimeoutMS=3000)
try:
client.admin.command("ping")
print("Connected to MongoDB")
except ConnectionFailure as e:
print("Connection failed:", e)Формат строки подключения
mongodb://[username:password@]host[:port][/database][?options]Распространённые параметры:
| Параметр | Пример | Назначение |
|---|---|---|
authSource | authSource=admin | База данных для аутентификации |
replicaSet | replicaSet=rs0 | Подключение к набору реплик |
tls=true | tls=true | Включить TLS/SSL |
serverSelectionTimeoutMS | serverSelectionTimeoutMS=5000 | Таймаут выбора сервера |
Базы данных и коллекции
MongoDB организует данные в двухуровневую иерархию:
- База данных группирует связанные коллекции (аналог схемы или базы данных в SQL).
- Коллекция содержит документы (аналог таблицы SQL, но без фиксированной схемы).
Обе создаются лениво — они начинают существовать в момент первой вставки документа. Команды CREATE DATABASE и CREATE TABLE не нужны.
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
# Reference a database (not yet created on disk)
db = client["mystore"]
# Reference a collection inside it (also not yet on disk)
products = db["products"]
# The database and collection are created when the first document is insertedБазовые CRUD-операции
Приведённые ниже примеры строятся один на другом. Если вы следуете руководству в интерактивном режиме, выполняйте их по порядку.
Create — вставка документов
Используйте insert_one() для одного документа и insert_many() для группы:
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
db = client["mystore"]
products = db["products"]
# Insert a single document
result = products.insert_one({
"name": "Laptop",
"brand": "Acme",
"price": 999.99,
"in_stock": True
})
print("Inserted id:", result.inserted_id)
# Insert multiple documents at once
new_products = [
{"name": "Mouse", "brand": "Acme", "price": 29.99, "in_stock": True},
{"name": "Keyboard", "brand": "Acme", "price": 79.99, "in_stock": False},
{"name": "Monitor", "brand": "Zeta", "price": 349.99, "in_stock": True},
]
batch_result = products.insert_many(new_products)
print("Inserted ids:", batch_result.inserted_ids)MongoDB автоматически добавляет поле _id (типа ObjectId) к каждому документу, если вы не указали его явно. Это поле является первичным ключом и всегда уникально в пределах коллекции.
Read — запрос документов
find_one() возвращает первый подходящий документ (или None). find() возвращает курсор, по которому можно итерироваться.
# Retrieve one document (no filter = the first document in natural order)
doc = products.find_one()
print(doc)
# Retrieve all documents in the collection
for p in products.find():
print(p["name"], "-", p["price"])
# Filter: products that are in stock
for p in products.find({"in_stock": True}):
print(p["name"])
# Projection: return only name and price (exclude _id)
for p in products.find({}, {"_id": 0, "name": 1, "price": 1}):
print(p)Операторы запросов
Язык запросов MongoDB использует операторы с префиксом $:
# Products cheaper than £100
cheap = products.find({"price": {"$lt": 100}})
# In-stock products from brand "Acme" or "Zeta"
multi = products.find({
"in_stock": True,
"brand": {"$in": ["Acme", "Zeta"]}
})
# Price between 50 and 500 (inclusive)
range_q = products.find({"price": {"$gte": 50, "$lte": 500}})Распространённые операторы сравнения:
| Оператор | Значение |
|---|---|
$eq | Равно (по умолчанию при использовании {"field": value}) |
$ne | Не равно |
$gt / $gte | Больше / больше или равно |
$lt / $lte | Меньше / меньше или равно |
$in | Значение входит в список |
$nin | Значение не входит в список |
Update — изменение документов
update_one() изменяет первый подходящий документ. update_many() изменяет все совпадения. Всегда используйте оператор $set для изменения конкретных полей — без него вы замените весь документ целиком.
# Update a single document: change the price of "Mouse"
update_result = products.update_one(
{"name": "Mouse"}, # filter
{"$set": {"price": 24.99}} # update
)
print("Matched:", update_result.matched_count,
"Modified:", update_result.modified_count)
# Mark all Acme products as in stock
products.update_many(
{"brand": "Acme"},
{"$set": {"in_stock": True}}
)
# Increment a field value
products.update_one(
{"name": "Laptop"},
{"$inc": {"price": -50}} # reduce price by 50
)Распространённые операторы обновления:
| Оператор | Действие |
|---|---|
$set | Установить одно или несколько полей |
$unset | Удалить поле |
$inc | Увеличить числовое поле |
$push | Добавить значение в array-поле |
$pull | Удалить значение из array-поля |
Delete — удаление документов
delete_one() удаляет первый подходящий документ. delete_many() удаляет все совпадения.
# Remove a single document
del_result = products.delete_one({"name": "Keyboard"})
print("Deleted count:", del_result.deleted_count)
# Remove all out-of-stock items
products.delete_many({"in_stock": False})
# Confirm what is left
print("Remaining products:")
for p in products.find({}, {"_id": 0, "name": 1}):
print(" -", p["name"])Типичные ловушки
Ленивое создание может скрывать опечатки
Поскольку MongoDB создаёт базы данных и коллекции по требованию, опечатка молча создаёт вторую пустую базу данных вместо того, чтобы выдать ошибку:
# Intended: client["mystore"] Actual: client["mystoree"]
db = client["mystoree"] # no error, but your data goes to the wrong databaseРешение: определяйте имена баз данных и коллекций как константы на уровне модуля:
DB_NAME = "mystore"
COL_NAME = "products"
db = client[DB_NAME]
products = db[COL_NAME]Ошибки соединения проявляются только при первой операции
MongoClient() завершается успешно, даже если MongoDB не запущена. Ошибка возникает только при выполнении реального запроса. Используйте serverSelectionTimeoutMS и проверку ping при запуске (как показано в разделе о подключении выше), чтобы быстро обнаруживать проблему.
Отсутствие $set заменяет весь документ
# WRONG — replaces the whole document with just {"price": 24.99}
products.update_one({"name": "Mouse"}, {"price": 24.99})
# CORRECT — only changes the price field
products.update_one({"name": "Mouse"}, {"$set": {"price": 24.99}})find() возвращает курсор, а не список
Курсор работает лениво — документы загружаются с сервера только по мере итерации. Если вам нужен обычный список, явно преобразуйте его:
all_products = list(products.find())Будьте осторожны с большими коллекциями: загрузка всего сразу в память может исчерпать RAM.
Что дальше
В этой главе рассмотрены основы. Остальные главы серии Python MongoDB подробнее раскрывают каждую тему:
- MongoDB Create Database — как работает ленивое создание и как проверить существование базы данных.
- MongoDB Create Collection — параметры создания коллекций и схемы валидации.
- MongoDB Insert —
insert_one(),insert_many()и обработка ошибок дублирующихся ключей. - MongoDB Find — проекции, курсоры и сортировка.
- MongoDB Query — полный справочник операторов запросов.
- MongoDB Update —
update_one(),update_many(),upsertи операторы массивов. - MongoDB Delete — безопасные шаблоны удаления и
drop(). - MongoDB Sort — сортировка по одному и нескольким полям.
- MongoDB Limit — пагинация с помощью
limit()иskip(). - MongoDB Drop Collection — полное удаление коллекции.