Сьогодні ми заглибимося в концепцію колекцій і документів у MongoDB, розберемося з принципами роботи з ними та поглянемо на важливі аспекти їх організації й оптимізації.
Колекції й документи: поняття та структура
Ми вже говорили про те, що MongoDB — документоорієнтована база даних. Це означає, що дані зберігаються не у вигляді таблиць, як у реляційних базах, а у вигляді колекцій документів. Колекції — це по суті контейнері (аналог таблиць в SQL), які зберігають документи.
Документи у MongoDB — це дані у форматі BSON (Binary JSON). Це розширення JSON, яке підтримує додаткові типи даних, такі як int, datetime та ін., що робить його дуже зручним для програмної обробки.
Приклад документа:
{
"_id": "63e8c0c89f1b5f001c854e4b",
"name": "Alice",
"email": "alice@example.com",
"age": 30,
"created_at": "2023-10-31T12:00:00Z"
}
Важлива особливість — автоматичне створення поля _id, яке слугує унікальним ідентифікатором для кожного документа в колекції.
Колекції не вимагають суворої схеми. Це означає, що два документи в одній колекції можуть мати різну структуру:
{
"_id": "63e8c0c89f1b5f001c854e4c",
"name": "Bob",
"phone": "+123456789"
}
Цікаво: відсутність суворої схеми не означає, що дані не мають структури. Зазвичай додатки все одно накладають бізнес-логіку на збережені дані.
Взаємодія з колекціями
Робота з колекціями в MongoDB в основному зводиться до використання методів для створення, читання, оновлення та видалення документів (CRUD), які ми вже знаємо. Однак є кілька важливих моментів:
- Створення колекції. MongoDB автоматично створює колекцію, щойно ти додаєш у неї перший документ. Це спрощує початкове налаштування.
- Перейменування. Колекцію можна перейменувати, зберігши її вміст.
- Видалення. Видалити колекцію можна, але тільки з явним підтвердженням. Це ніби "неначе випадково не натиснув на
rm -rf /?"
Приклад на Python для створення та видалення колекції:
from motor.motor_asyncio import AsyncIOMotorClient
client = AsyncIOMotorClient("mongodb://localhost:27017")
db = client.test_database
# Колекція створюється автоматично
collection = db.my_collection
# Видалення колекції
await collection.drop()
Індексація даних у MongoDB
Індекси в MongoDB, як і в реляційних базах, використовуються для прискорення пошуку даних. Вони створюються на основі одного або кількох полів документа в колекції.
Коли ти створюєш запит до MongoDB, вона або:
- Шукає результат з використанням індексу (швидко), або
- Проводить повний обхід усіх документів у колекції (повільно, якщо колекція велика).
Приклад індексації:
# Створюємо індекс на поле 'email'
await collection.create_index("email", unique=True)
Види індексів
MongoDB підтримує кілька видів індексів:
- Одиночні індекси (single field index) — для одного поля.
- Складені індекси (compound index) — для кількох полів.
- Текстові індекси (text index) — для повнотекстового пошуку.
- Унікальні індекси (unique index) — для забезпечення унікальності значень.
Приклад створення складеного індексу:
# Індекс для комбінації 'name' + 'email'
await collection.create_index([("name", 1), ("email", -1)])
Тут 1 і -1 означають сортування (1 — по зростанню, -1 — по спаданню).
Щоб переглянути всі індекси колекції, використовуй:
indexes = await collection.index_information()
print(indexes)
Забезпечення цілісності даних
На відміну від ранніх версій, сучасні версії MongoDB підтримують повноцінні транзакції. Це означає, що ти можеш виконати декілька операцій (наприклад, додавання в одну колекцію і видалення з іншої) як атомарну дію.
Приклад транзакції:
async with client.start_session() as session:
async with session.start_transaction():
await collection1.insert_one({"_id": 1, "name": "Alice"}, session=session)
await collection2.delete_one({"_id": 1}, session=session)
Якщо щось піде не так, транзакція буде відкотена.
Робота з ACID
MongoDB підтримує основні властивості ACID:
- Atomicity (атомарність): усі операції всередині транзакції виконуються або не виконуються взагалі.
- Consistency (узгодженість): після виконання транзакції база залишається в узгодженому стані.
- Isolation (ізоляція): зміни, зроблені транзакцією, видимі лише цій транзакції, доки вона не завершиться.
- Durability (довговічність): після завершення транзакції її зміни гарантовано зберігаються.
Приклад роботи з колекціями в реальному додатку
Зробимо додаток на FastAPI для роботи з колекцією користувачів. Реалізуємо базовий CRUD API.
from fastapi import FastAPI, HTTPException
from motor.motor_asyncio import AsyncIOMotorClient
from bson import ObjectId
app = FastAPI()
client = AsyncIOMotorClient("mongodb://localhost:27017")
db = client.my_database
users_collection = db.users
# Допоміжна функція для перетворення ObjectId у рядок
def user_helper(user):
return {
"id": str(user["_id"]),
"name": user["name"],
"email": user["email"]
}
@app.get("/users")
async def get_all_users():
users = await users_collection.find().to_list(100)
return [user_helper(user) for user in users]
@app.post("/users")
async def create_user(user: dict):
result = await users_collection.insert_one(user)
created_user = await users_collection.find_one({"_id": result.inserted_id})
return user_helper(created_user)
@app.get("/users/{user_id}")
async def get_user(user_id: str):
user = await users_collection.find_one({"_id": ObjectId(user_id)})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user_helper(user)
@app.put("/users/{user_id}")
async def update_user(user_id: str, updated_data: dict):
result = await users_collection.update_one({"_id": ObjectId(user_id)}, {"$set": updated_data})
if result.modified_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return {"msg": "User updated successfully"}
@app.delete("/users/{user_id}")
async def delete_user(user_id: str):
result = await users_collection.delete_one({"_id": ObjectId(user_id)})
if result.deleted_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return {"msg": "User deleted successfully"}
Цей API дозволить:
- Додавати нових користувачів.
- Отримувати список користувачів.
- Отримувати дані про конкретного користувача.
- Оновлювати інформацію.
- Видаляти користувача.
MongoDB дозволяє гнучко й ефективно працювати з колекціями та документами, що робить її відмінним вибором для сучасних проєктів. У наступній лекції розглянемо ще більш просунуті техніки роботи з MongoDB і FastAPI.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ