153 lines
4.5 KiB
Python
153 lines
4.5 KiB
Python
"""
|
|
MongoDB CRUD Operation Mixins.
|
|
|
|
This module provides mixins for common MongoDB operations:
|
|
1. Document creation (insert)
|
|
2. Document retrieval (find)
|
|
3. Document updates
|
|
4. Document deletion
|
|
5. Aggregation operations
|
|
"""
|
|
|
|
from typing import Any, Dict, List, Optional
|
|
from functools import wraps
|
|
|
|
from pymongo.collection import Collection
|
|
from pymongo.errors import (
|
|
ConnectionFailure,
|
|
OperationFailure,
|
|
ServerSelectionTimeoutError,
|
|
PyMongoError,
|
|
)
|
|
|
|
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
|
|
|
|
|
|
def handle_mongo_errors(func):
|
|
"""Decorator to handle MongoDB operation errors.
|
|
|
|
Catches MongoDB-specific errors and converts them to HTTPExceptionApi.
|
|
"""
|
|
|
|
@wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
try:
|
|
return func(*args, **kwargs)
|
|
except ConnectionFailure:
|
|
raise HTTPExceptionApi(error_code="HTTP_503_SERVICE_UNAVAILABLE", lang="en")
|
|
except ServerSelectionTimeoutError:
|
|
raise HTTPExceptionApi(error_code="HTTP_504_GATEWAY_TIMEOUT", lang="en")
|
|
except OperationFailure as e:
|
|
raise HTTPExceptionApi(error_code="HTTP_400_BAD_REQUEST", lang="en")
|
|
except PyMongoError as e:
|
|
raise HTTPExceptionApi(
|
|
error_code="HTTP_500_INTERNAL_SERVER_ERROR", lang="en"
|
|
)
|
|
|
|
return wrapper
|
|
|
|
|
|
class MongoInsertMixin:
|
|
"""Mixin for MongoDB insert operations."""
|
|
|
|
@handle_mongo_errors
|
|
def insert_one(self, collection: Collection, document: Dict[str, Any]):
|
|
"""Insert a single document into the collection."""
|
|
result = collection.insert_one(document)
|
|
return result
|
|
|
|
@handle_mongo_errors
|
|
def insert_many(self, collection: Collection, documents: List[Dict[str, Any]]):
|
|
"""Insert multiple documents into the collection."""
|
|
result = collection.insert_many(documents)
|
|
return result
|
|
|
|
|
|
class MongoFindMixin:
|
|
"""Mixin for MongoDB find operations."""
|
|
|
|
@handle_mongo_errors
|
|
def find_one(
|
|
self,
|
|
collection: Collection,
|
|
filter_query: Dict[str, Any],
|
|
projection: Optional[Dict[str, Any]] = None,
|
|
):
|
|
"""Find a single document in the collection."""
|
|
result = collection.find_one(filter_query, projection)
|
|
return result
|
|
|
|
@handle_mongo_errors
|
|
def find_many(
|
|
self,
|
|
collection: Collection,
|
|
filter_query: Dict[str, Any],
|
|
projection: Optional[Dict[str, Any]] = None,
|
|
sort: Optional[List[tuple]] = None,
|
|
limit: Optional[int] = None,
|
|
skip: Optional[int] = None,
|
|
):
|
|
"""Find multiple documents in the collection with pagination support."""
|
|
cursor = collection.find(filter_query, projection)
|
|
if sort:
|
|
cursor = cursor.sort(sort)
|
|
if skip:
|
|
cursor = cursor.skip(skip)
|
|
if limit:
|
|
cursor = cursor.limit(limit)
|
|
return list(cursor)
|
|
|
|
|
|
class MongoUpdateMixin:
|
|
"""Mixin for MongoDB update operations."""
|
|
|
|
@handle_mongo_errors
|
|
def update_one(
|
|
self,
|
|
collection: Collection,
|
|
filter_query: Dict[str, Any],
|
|
update_data: Dict[str, Any],
|
|
upsert: bool = False,
|
|
):
|
|
"""Update a single document in the collection."""
|
|
result = collection.update_one(filter_query, update_data, upsert=upsert)
|
|
return result
|
|
|
|
@handle_mongo_errors
|
|
def update_many(
|
|
self,
|
|
collection: Collection,
|
|
filter_query: Dict[str, Any],
|
|
update_data: Dict[str, Any],
|
|
upsert: bool = False,
|
|
):
|
|
"""Update multiple documents in the collection."""
|
|
result = collection.update_many(filter_query, update_data, upsert=upsert)
|
|
return result
|
|
|
|
|
|
class MongoDeleteMixin:
|
|
"""Mixin for MongoDB delete operations."""
|
|
|
|
@handle_mongo_errors
|
|
def delete_one(self, collection: Collection, filter_query: Dict[str, Any]):
|
|
"""Delete a single document from the collection."""
|
|
result = collection.delete_one(filter_query)
|
|
return result
|
|
|
|
@handle_mongo_errors
|
|
def delete_many(self, collection: Collection, filter_query: Dict[str, Any]):
|
|
"""Delete multiple documents from the collection."""
|
|
result = collection.delete_many(filter_query)
|
|
return result
|
|
|
|
|
|
class MongoAggregateMixin:
|
|
"""Mixin for MongoDB aggregation operations."""
|
|
|
|
@handle_mongo_errors
|
|
def aggregate(self, collection: Collection, pipeline: List[Dict[str, Any]]):
|
|
"""Execute an aggregation pipeline on the collection."""
|
|
result = collection.aggregate(pipeline)
|
|
return result
|