Skip to content

Commit

Permalink
#22: feat: add clients for MongoDB database and collection
Browse files Browse the repository at this point in the history
  • Loading branch information
ReznikovRoman committed Jul 9, 2022
1 parent fe5065d commit d486fb6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/ugc/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def get_mongodb_url(cls, value, values) -> str:
host = values["MONGODB_HOST"]
port = values["MONGODB_PORT"]
database = values["MONGODB_NAME"]
return f"mongodb://{user}:{password}@{host}:{port}/{database}"
return f"mongodb://{user}:{password}@{host}:{port}/{database}?authSource=admin"


@lru_cache()
Expand Down
42 changes: 42 additions & 0 deletions src/ugc/infrastructure/db/clients.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from motor.core import AgnosticCollection, AgnosticDatabase
from pymongo import results


class MongoDatabaseClient:
"""Клиент для работы с базой данной из MongoDB."""

collection_cache: dict[tuple, "MongoCollectionClient"] = {}

def __init__(self, db_client: AgnosticDatabase) -> None:
assert isinstance(db_client, AgnosticDatabase)
self._client = db_client

def __getattr__(self, name: str) -> "MongoCollectionClient":
if name.startswith("_"):
raise AttributeError(f"Cannot access private collection <{name}>")
return self[name]

def __getitem__(self, name: str) -> "MongoCollectionClient":
mongo_client = self._client.__getattr__(name)
return self._get_collection_client(name, mongo_client)

def _get_collection_client(self, name: str, mongo_client: AgnosticCollection) -> "MongoCollectionClient":
cache_key = ("MongoCollectionClient", name, self.__module__)
cached_client = self.collection_cache.get(cache_key)
if cached_client:
return cached_client
new_client = MongoCollectionClient(collection_client=mongo_client)
return new_client


class MongoCollectionClient:
"""Клиент для работы с коллекций документов MongoDB."""

def __init__(self, collection_client: AgnosticCollection) -> None:
assert isinstance(collection_client, AgnosticCollection)
self._client = collection_client

async def insert_one(self, document: dict) -> results.InsertOneResult:
"""Добавление одного документа в коллекцию."""
result = await self._client.insert_one(document)
return result
24 changes: 22 additions & 2 deletions src/ugc/infrastructure/db/mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,33 @@
from typing import TYPE_CHECKING, AsyncIterator

import motor.motor_asyncio
from pymongo import ASCENDING, IndexModel

from .clients import MongoDatabaseClient

if TYPE_CHECKING:
from motor.core import AgnosticClient, AgnosticDatabase


async def init_mongo(url: str) -> AsyncIterator[AgnosticDatabase]:
async def init_mongo(url: str) -> AsyncIterator[MongoDatabaseClient]:
mongo_client: AgnosticClient = motor.motor_asyncio.AsyncIOMotorClient(url)
mongo_default_db: AgnosticDatabase = mongo_client.get_default_database()
yield mongo_default_db
await configure_db(mongo_default_db)
db_client = MongoDatabaseClient(mongo_default_db)
yield db_client
mongo_client.close


async def configure_db(db_client: AgnosticDatabase) -> AgnosticDatabase:
await create_indexes(db_client)
return db_client


async def create_indexes(db_client: AgnosticDatabase) -> AgnosticDatabase:
review_unique_index = IndexModel(
keys=[("user_id", ASCENDING), ("film_id", ASCENDING)],
name="review_film_user_unq",
unique=True,
)
await db_client.reviews.create_indexes([review_unique_index])
return db_client

0 comments on commit d486fb6

Please sign in to comment.