""" MongoDB database connection and operations. This module provides MongoDB connection management with: 1. Connection pooling 2. Lifecycle management 3. Error handling """ from typing import Optional, Dict, Any, List, Union from pymongo import MongoClient from pymongo.results import InsertOneResult, DeleteResult, UpdateResult from pymongo.cursor import Cursor from AllConfigs.NoSqlDatabase.configs import MongoConfig class MongoInsertMixin: """Mixin for MongoDB insert operations.""" def insert_one(self, document: Dict[str, Any]) -> InsertOneResult: """Insert a single document.""" return self.collection.insert_one(document) def insert_many(self, documents: List[Dict[str, Any]]) -> List[InsertOneResult]: """Insert multiple documents.""" return self.collection.insert_many(documents) class MongoFindMixin: """Mixin for MongoDB find operations.""" def find_one(self, filter_query: Dict[str, Any]) -> Optional[Dict[str, Any]]: """Find a single document.""" return self.collection.find_one(filter_query) def find_many(self, filter_query: Dict[str, Any]) -> Cursor: """Find multiple documents.""" return self.collection.find(filter_query) class MongoUpdateMixin: """Mixin for MongoDB update operations.""" def update_one( self, filter_query: Dict[str, Any], update: Dict[str, Any] ) -> UpdateResult: """Update a single document.""" return self.collection.update_one(filter_query, update) def update_many( self, filter_query: Dict[str, Any], update: Dict[str, Any] ) -> UpdateResult: """Update multiple documents.""" return self.collection.update_many(filter_query, update) class MongoDeleteMixin: """Mixin for MongoDB delete operations.""" def delete_one(self, filter_query: Dict[str, Any]) -> DeleteResult: """Delete a single document.""" return self.collection.delete_one(filter_query) def delete_many(self, filter_query: Dict[str, Any]) -> DeleteResult: """Delete multiple documents.""" return self.collection.delete_many(filter_query) class MongoAggregateMixin: """Mixin for MongoDB aggregate operations.""" def aggregate(self, pipeline: List[Dict[str, Any]]) -> Cursor: """Execute an aggregation pipeline.""" return self.collection.aggregate(pipeline) class MongoDBHandler( MongoInsertMixin, MongoFindMixin, MongoUpdateMixin, MongoDeleteMixin, MongoAggregateMixin, ): """Handler for MongoDB operations with connection management.""" _instance = None _client: Optional[MongoClient] = None def __new__(cls): """Implement singleton pattern for database connection.""" if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance def __init__(self): """Initialize MongoDB connection if not already initialized.""" if not self._client: # Build connection URL based on whether credentials are provided if MongoConfig.USER_NAME and MongoConfig.PASSWORD: connection_url = ( f"mongodb://{MongoConfig.USER_NAME}:{MongoConfig.PASSWORD}" f"@{MongoConfig.HOST}:{MongoConfig.PORT}" ) else: connection_url = f"mongodb://{MongoConfig.HOST}:{MongoConfig.PORT}" # Build connection options connection_kwargs = { "host": connection_url, "maxPoolSize": 50, # Maximum number of connections in the pool "minPoolSize": 10, # Minimum number of connections in the pool "maxIdleTimeMS": 30000, # Maximum time a connection can be idle (30 seconds) "waitQueueTimeoutMS": 2000, # How long a thread will wait for a connection "serverSelectionTimeoutMS": 5000, # How long to wait for server selection } self._client = MongoClient(**connection_kwargs) # Test connection self._client.admin.command("ping") def close(self): """Close MongoDB connection.""" if self._client: self._client.close() self._client = None def __del__(self): """Ensure connection is closed on deletion.""" self.close() @property def client(self) -> MongoClient: """Get MongoDB client.""" return self._client def get_database(self, database_name: str = None): """Get MongoDB database.""" db_name = database_name or MongoConfig.DATABASE_NAME return self._client[db_name] def get_collection(self, collection_name: str, database_name: str = None): """Get MongoDB collection.""" database = self.get_database(database_name) return database[collection_name] # Create a singleton instance mongodb = MongoDBHandler()