Продовжуємо нашу захопливу подорож у світ MongoDB і баз даних NoSQL.
На попередніх лекціях ми ознайомилися з основами MongoDB: розібрали її архітектуру, можливості та навчилися підключати її до наших проєктів.
Сьогодні настав час зануритися в саму суть роботи з MongoDB — основні операції з даними.
Говорячи простіше, навчимося створювати, читати, оновлювати і видаляти дані (CRUD-операції).
CRUD — це база при роботі з будь-якою базою даних. MongoDB пропонує дуже гнучкий і лаконічний інтерфейс для роботи з даними.
CRUD розшифровується як:
- Create (створення) — додавання нових даних (документів) у колекцію.
- Read (читання) — витягування даних з колекції.
- Update (оновлення) — змінення існуючих даних.
- Delete (видалення) — видалення даних.
Давай по черзі розберемо кожну операцію.
1. Створення (Create)
Додати дані в MongoDB можна за допомогою методів insert_one і insert_many.
Приклад: додавання одного документа.
Метод insert_one дозволяє додати один документ у колекцію.
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi import FastAPI
app = FastAPI()
# Підключення до MongoDB
client = AsyncIOMotorClient("mongodb://localhost:27017")
db = client.my_database
collection = db.my_collection
@app.post("/create")
async def create_document():
document = {"name": "Alice", "age": 25, "city": "Wonderland"}
result = await collection.insert_one(document)
return {"inserted_id": str(result.inserted_id)}
👉 Зверни увагу: MongoDB автоматично додає поле _id, якщо ти його не вказав. Це унікальний ідентифікатор документа.
Давай у наступному прикладі додамо одразу кілька документів.
Для цього стане в пригоді метод insert_many.
@app.post("/create_many")
async def create_many_documents():
documents = [
{"name": "Bob", "age": 30, "city": "Atlantis"},
{"name": "Charlie", "age": 28, "city": "Springfield"}
]
results = await collection.insert_many(documents)
return {"inserted_ids": [str(id) for id in results.inserted_ids]}
2. Читання (Read)
Найпопулярніша операція — витягнути дані з бази. MongoDB надає кілька методів для читання даних, включаючи find_one і find.
Метод find_one дозволяє отримати перший підходящий документ.
@app.get("/read_one")
async def read_one_document():
result = await collection.find_one({"name": "Alice"})
return result
👉 Корисний факт: Повернутий документ — це просто словник Python. Зручно, правда?
А метод find повертає всі документи, що відповідають вказаним критеріям.
@app.get("/read_many")
async def read_many_documents():
cursor = collection.find({"age": {"$gt": 20}}) # Документи, де age > 20
results = []
async for document in cursor:
results.append(document)
return results
MongoDB підтримує багато операторів для фільтрації даних:
$gtі$gte: більше і більше або дорівнює.$ltі$lte: менше і менше або дорівнює.$eqі$ne: дорівнює і не дорівнює.$inі$nin: входить або не входить у масив.
Приклад фільтрації з кількома умовами:
criteria = {"age": {"$gt": 20}, "city": "Springfield"}
3. Оновлення (Update)
Для зміни існуючих даних використовуються методи update_one, update_many і replace_one.
Метод update_one оновлює перший знайдений документ.
@app.put("/update_one")
async def update_one_document():
filter = {"name": "Alice"}
update = {"$set": {"age": 26}}
result = await collection.update_one(filter, update)
return {"matched_count": result.matched_count, "modified_count": result.modified_count}
👉 Важливо: ми використовуємо оператор $set, щоб вказати, які поля треба оновити.
Метод update_many оновлює всі документи, що відповідають фільтру.
@app.put("/update_many")
async def update_many_documents():
filter = {"city": "Wonderland"}
update = {"$set": {"city": "Neverland"}}
result = await collection.update_many(filter, update)
return {"matched_count": result.matched_count, "modified_count": result.modified_count}
Якщо хочеш повністю замінити документ, то використовуй метод replace_one.
@app.put("/replace_one")
async def replace_one_document():
filter = {"name": "Charlie"}
new_document = {"name": "Charlie", "age": 35, "country": "USA"}
result = await collection.replace_one(filter, new_document)
return {"matched_count": result.matched_count, "modified_count": result.modified_count}
4. Видалення (Delete)
Методи delete_one і delete_many виконують видалення даних.
Метод delete_one видаляє перший підходящий документ.
@app.delete("/delete_one")
async def delete_one_document():
filter = {"name": "Alice"}
result = await collection.delete_one(filter)
return {"deleted_count": result.deleted_count}
Метод delete_many видаляє всі документи, що відповідають фільтру.
@app.delete("/delete_many")
async def delete_many_documents():
filter = {"city": "Neverland"}
result = await collection.delete_many(filter)
return {"deleted_count": result.deleted_count}
Помилки та особливості при роботі з CRUD
- Відсутність схеми: MongoDB не вимагає вказувати схему для даних, що може призвести до неструктурованих даних. Слідкуй за консистентністю даних вручну або використовуй валідацію на рівні додатку.
- Ідентифікатор
_id: значення_idмає бути унікальним. Якщо ти намагаєшся додати документ з уже існуючим_id, отримаєш помилку. - Порожній фільтр: якщо передаси порожній фільтр в
delete_manyабоupdate_many, всі документи в колекції будуть зачеплені. Це популярна помилка новачків.
Практика: створюємо додаток для керування користувачами
Давай швидко зберемо API, що дозволяє керувати колекцією користувачів.
У нас будуть маршрути для створення, читання, оновлення і видалення користувачів.
@app.post("/users")
async def create_user(user: dict):
result = await collection.insert_one(user)
return {"inserted_id": str(result.inserted_id)}
@app.get("/users")
async def read_users():
cursor = collection.find({})
users = await cursor.to_list(length=100)
return users
@app.put("/users/{user_id}")
async def update_user(user_id: str, user: dict):
filter = {"_id": user_id}
update = {"$set": user}
result = await collection.update_one(filter, update)
return {"modified_count": result.modified_count}
@app.delete("/users/{user_id}")
async def delete_user(user_id: str):
filter = {"_id": user_id}
result = await collection.delete_one(filter)
return {"deleted_count": result.deleted_count}
Ці маршрути допоможуть тобі краще зрозуміти CRUD-операції на практиці.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ