JavaRush /Курси /Модуль 4: FastAPI /Приклад роботи з PostgreSQL і MongoDB в одному застосунку...

Приклад роботи з PostgreSQL і MongoDB в одному застосунку

Модуль 4: FastAPI
Рівень 10 , Лекція 4
Відкрита

Сьогодні ми розглянемо інтеграцію реляційної й нереляційної баз даних в одному застосунку. Так, це як з'їсти одночасно піцу й суші — звучить дивно, але іноді без такого поєднання не обійтись.

Уявіть собі велике застосунок електронної комерції. У вас є величезний каталог продуктів, інформація про клієнтів, замовлення й платежі. Що зберігати в PostgreSQL? Логічно зберегти там транзакції, які потребують суворої цілісності. А MongoDB чудово підходить для зберігання відгуків користувачів про товари — вони різноманітні за структурою й часто змінюються. У таких випадках комбінування реляційних і нереляційних баз даних дозволяє досягти одночасно надійності й гнучкості.


Архітектура застосунку з двома базами даних

Коли ми говоримо про проєкт з інтеграцією PostgreSQL і MongoDB, нам треба врахувати такий план:

  1. PostgreSQL для зберігання структурованих і критично важливих даних.
  2. MongoDB для зберігання великих обсягів неструктурованих даних.
  3. API-інтерфейс для взаємодії з обома базами даних.
  4. Чіткий розподіл задач між базами даних.

Головні принципи такої архітектури:

  • Розподіл відповідальності: кожен тип даних обробляється в системі, найбільш підходящій для нього.
  • Синхронізація даних і їхня цілісність: визначте, де дані мають бути пов'язані й як забезпечити синхронність.
  • Продуктивність: забезпечте швидкий доступ до даних там, де це важливо.

Встановлення і налаштування застосунку

Якщо в вас ще не встановлені PostgreSQL і MongoDB, встановіть їх. Для PostgreSQL можна використовувати офіційну документацію PostgreSQL, а для MongoDB — керівництво з інсталяції MongoDB.

Ми також будемо використовувати asyncpg і motor для роботи з PostgreSQL і MongoDB через Python.

Встановимо необхідні залежності:

pip install asyncpg motor fastapi uvicorn

У файлі config.py визначимо параметри підключень для баз даних:


POSTGRES_URL = "postgresql://user:password@localhost:5432/mydb"
MONGO_URL = "mongodb://localhost:27017"

Створимо модуль для підключення до PostgreSQL:


import asyncpg

class PostgresConnection:
    def __init__(self, dsn):
        self.dsn = dsn
        self.connection = None

    async def connect(self):
        self.connection = await asyncpg.connect(self.dsn)

    async def disconnect(self):
        if self.connection:
            await self.connection.close()

postgres = PostgresConnection(dsn="postgresql://user:password@localhost:5432/mydb")

Створюємо модуль для підключення до MongoDB:


from motor.motor_asyncio import AsyncIOMotorClient

class MongoDBConnection:
    def __init__(self, url):
        self.url = url
        self.client = None

    async def connect(self):
        self.client = AsyncIOMotorClient(self.url)
        self.database = self.client.mydb

    async def disconnect(self):
        if self.client:
            self.client.close()

mongo = MongoDBConnection(url="mongodb://localhost:27017")

Робота з базами даних: приклади

Давайте уявимо, що наш застосунок зберігає дані про замовлення в PostgreSQL і відгуки на товари в MongoDB.

Створимо таблицю замовлень в PostgreSQL:


CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_name TEXT NOT NULL,
    amount NUMERIC NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Додамо функцію для додавання замовлення:


async def create_order(customer_name: str, amount: float):
    query = "INSERT INTO orders (customer_name, amount) VALUES ($1, $2) RETURNING id;"
    return await postgres.connection.fetchval(query, customer_name, amount)

Створимо функцію для читання замовлень:


async def get_orders():
    query = "SELECT * FROM orders;"
    return await postgres.connection.fetch(query)

Відгуки — це неструктуровані дані, тому MongoDB підходить відмінно. Наприклад:


{
    "product_id": "12345",
    "review": "Чудовий товар!",
    "rating": 5,
    "timestamp": "2023-10-03T12:00:00Z"
}

Додамо функцію для додавання відгука:


async def add_review(review: dict):
    return await mongo.database.reviews.insert_one(review)

Додамо функцію для отримання відгуків про продукт:


async def get_reviews(product_id: str):
    return await mongo.database.reviews.find({"product_id": product_id}).to_list(100)

Інтеграція в FastAPI

Тепер об'єднаємо наші бази даних в API. У файлі main.py:


from fastapi import FastAPI
from config import POSTGRES_URL, MONGO_URL
from databases import postgres, mongo, create_order, get_orders, add_review, get_reviews

app = FastAPI()

@app.on_event("startup")
async def startup():
    await postgres.connect()
    await mongo.connect()

@app.on_event("shutdown")
async def shutdown():
    await postgres.disconnect()
    await mongo.disconnect()

@app.post("/orders/")
async def create_new_order(customer_name: str, amount: float):
    order_id = await create_order(customer_name, amount)
    return {"id": order_id}

@app.get("/orders/")
async def list_orders():
    orders = await get_orders()
    return {"orders": orders}

@app.post("/reviews/")
async def create_review(review: dict):
    result = await add_review(review)
    return {"id": str(result.inserted_id)}

@app.get("/reviews/{product_id}")
async def list_reviews(product_id: str):
    reviews = await get_reviews(product_id)
    return {"reviews": reviews}

Запустимо сервер:

uvicorn main:app --reload

Приклад роботи

  1. Створюємо нове замовлення:
    POST /orders/
    
    {
        "customer_name": "Іван Іванов",
        "amount": 1500.75
    }
    
    Відповідь:
    
    {
        "id": 1
    }
    
  2. Додаємо відгук:
    POST /reviews/
    
    {
        "product_id": "12345",
        "review": "Чудовий товар!",
        "rating": 5
    }
    
    Відповідь:
    
    {
        "id": "64f765ad7b8e5a192cfa3d73"
    }
    
  3. Отримуємо список замовлень:
    GET /orders/ Відповідь:
    
    {
        "orders": [
            {
                "id": 1,
                "customer_name": "Іван Іванов",
                "amount": 1500.75,
                "created_at": "2023-10-03T14:00:00Z"
            }
        ]
    }
    
  4. Отримуємо відгуки про продукт:
    GET /reviews/12345 Відповідь:
    
    {
        "reviews": [
            {
                "product_id": "12345",
                "review": "Чудовий товар!",
                "rating": 5,
                "timestamp": "2023-10-03T14:30:00Z"
            }
        ]
    }
    

Особливості та складнощі

Робота з двома базами даних може здатися складною з точки зору їхньої синхронізації. Наприклад, метаінформація з PostgreSQL може знадобитися в MongoDB. У такому випадку краще використовувати фреймворки на кшталт Kafka для забезпечення подійної синхронізації, але це вже тема для іншої лекції.

3
Опитування
Основні відмінності між SQL і NoSQL базами даних, рівень 10, лекція 4
Недоступний
Основні відмінності між SQL і NoSQL базами даних
Основні відмінності між SQL і NoSQL базами даних
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ