updated docs
This commit is contained in:
@@ -7,10 +7,12 @@ This module provides MongoDB connection management with:
|
||||
3. Error handling
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List, Union
|
||||
from typing import Optional, Dict, Any, List, Union, Callable
|
||||
from contextlib import contextmanager
|
||||
from pymongo import MongoClient
|
||||
from pymongo.results import InsertOneResult, DeleteResult, UpdateResult
|
||||
from pymongo.cursor import Cursor
|
||||
from functools import wraps
|
||||
|
||||
from AllConfigs.NoSqlDatabase.configs import MongoConfig
|
||||
|
||||
@@ -96,39 +98,44 @@ class MongoDBHandler(
|
||||
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,
|
||||
"host": MongoConfig.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 __enter__(self):
|
||||
"""Context manager entry point."""
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
"""Context manager exit point - ensures connection is properly closed."""
|
||||
try:
|
||||
if self._client:
|
||||
self._client.close()
|
||||
self._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
return False # Don't suppress any exceptions
|
||||
|
||||
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()
|
||||
try:
|
||||
if self._client:
|
||||
self._client.close()
|
||||
self._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
|
||||
@property
|
||||
def client(self) -> MongoClient:
|
||||
@@ -145,6 +152,41 @@ class MongoDBHandler(
|
||||
database = self.get_database(database_name)
|
||||
return database[collection_name]
|
||||
|
||||
# Create a function to get the singleton instance
|
||||
@classmethod
|
||||
@contextmanager
|
||||
def get_mongodb(cls):
|
||||
"""Get or create the MongoDB singleton instance as a context manager."""
|
||||
instance = cls()
|
||||
try:
|
||||
yield instance
|
||||
finally:
|
||||
try:
|
||||
if instance._client:
|
||||
instance._client.close()
|
||||
instance._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
|
||||
# Create a singleton instance
|
||||
@classmethod
|
||||
def with_mongodb(cls, func: Callable):
|
||||
"""Decorator to automatically handle MongoDB connection context.
|
||||
|
||||
Usage:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def my_function(db, *args, **kwargs):
|
||||
# db is the MongoDB instance
|
||||
pass
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
with cls.get_mongodb() as db:
|
||||
return func(db, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
# Create a singleton instance for backward compatibility
|
||||
mongodb = MongoDBHandler()
|
||||
|
||||
@@ -5,25 +5,28 @@ This module provides practical examples of using MongoDB operations through our
|
||||
Each example demonstrates different aspects of CRUD operations and aggregation.
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Any
|
||||
import arrow
|
||||
from datetime import datetime
|
||||
|
||||
from Services.MongoDb.database import mongodb
|
||||
from Services.MongoDb.database import MongoDBHandler
|
||||
|
||||
|
||||
def insert_examples() -> None:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def insert_examples(db) -> None:
|
||||
"""Examples of insert operations."""
|
||||
# Get the collection
|
||||
users_collection = db.get_collection("users")
|
||||
products_collection = db.get_collection("products")
|
||||
|
||||
# Single document insert
|
||||
user_doc = {
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"age": 30,
|
||||
"created_at": datetime.utcnow(),
|
||||
"created_at": datetime.now(),
|
||||
}
|
||||
user_id = mongodb.insert_one(
|
||||
database="user_db", collection="users", document=user_doc
|
||||
)
|
||||
print(f"Inserted user with ID: {user_id}")
|
||||
result = users_collection.insert_one(user_doc)
|
||||
print(f"Inserted user with ID: {result.inserted_id}")
|
||||
|
||||
# Multiple documents insert
|
||||
products = [
|
||||
@@ -31,80 +34,68 @@ def insert_examples() -> None:
|
||||
{"name": "Mouse", "price": 29.99, "stock": 100},
|
||||
{"name": "Keyboard", "price": 59.99, "stock": 75},
|
||||
]
|
||||
product_ids = mongodb.insert_many(
|
||||
database="store_db", collection="products", documents=products
|
||||
)
|
||||
print(f"Inserted {len(product_ids)} products")
|
||||
result = products_collection.insert_many(products)
|
||||
print(f"Inserted {len(result.inserted_ids)} products")
|
||||
|
||||
|
||||
def find_examples() -> None:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def find_examples(db) -> None:
|
||||
"""Examples of find operations."""
|
||||
# Get the collections
|
||||
users_collection = db.get_collection("users")
|
||||
products_collection = db.get_collection("products")
|
||||
|
||||
# Find one document
|
||||
user = mongodb.find_one(
|
||||
database="user_db",
|
||||
collection="users",
|
||||
filter_query={"email": "john@example.com"},
|
||||
projection={"username": 1, "email": 1, "_id": 0},
|
||||
)
|
||||
user = users_collection.find_one({"email": "john@example.com"})
|
||||
print(f"Found user: {user}")
|
||||
|
||||
# Find many with pagination
|
||||
page_size = 10
|
||||
page_number = 1
|
||||
products = mongodb.find_many(
|
||||
database="store_db",
|
||||
collection="products",
|
||||
filter_query={"price": {"$lt": 100}},
|
||||
projection={"name": 1, "price": 1},
|
||||
sort=[("price", 1)], # Sort by price ascending
|
||||
limit=page_size,
|
||||
skip=(page_number - 1) * page_size,
|
||||
)
|
||||
# Find many documents
|
||||
products_cursor = products_collection.find({"price": {"$lt": 100}})
|
||||
products = list(products_cursor)
|
||||
print(f"Found {len(products)} products under $100")
|
||||
|
||||
|
||||
def update_examples() -> None:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def update_examples(db) -> None:
|
||||
"""Examples of update operations."""
|
||||
# Get the collections
|
||||
products_collection = db.get_collection("products")
|
||||
|
||||
# Update single document
|
||||
result = mongodb.update_one(
|
||||
database="store_db",
|
||||
collection="products",
|
||||
filter_query={"name": "Laptop"},
|
||||
update_data={"price": 899.99, "stock": 45},
|
||||
upsert=False,
|
||||
result = products_collection.update_one(
|
||||
{"name": "Laptop"}, {"$set": {"price": 899.99, "stock": 45}}
|
||||
)
|
||||
print(f"Updated {result['modified_count']} laptop(s)")
|
||||
print(f"Updated {result.modified_count} laptop(s)")
|
||||
|
||||
# Update multiple documents
|
||||
result = mongodb.update_many(
|
||||
database="store_db",
|
||||
collection="products",
|
||||
filter_query={"stock": {"$lt": 10}},
|
||||
update_data={"status": "low_stock"},
|
||||
upsert=True,
|
||||
result = products_collection.update_many(
|
||||
{"stock": {"$lt": 10}}, {"$set": {"status": "low_stock"}}
|
||||
)
|
||||
print(f"Updated {result['modified_count']} low stock products")
|
||||
print(f"Updated {result.modified_count} low stock products")
|
||||
|
||||
|
||||
def delete_examples() -> None:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def delete_examples(db) -> None:
|
||||
"""Examples of delete operations."""
|
||||
# Get the collections
|
||||
users_collection = db.get_collection("users")
|
||||
products_collection = db.get_collection("products")
|
||||
|
||||
# Delete single document
|
||||
count = mongodb.delete_one(
|
||||
database="user_db",
|
||||
collection="users",
|
||||
filter_query={"email": "john@example.com"},
|
||||
)
|
||||
print(f"Deleted {count} user")
|
||||
result = users_collection.delete_one({"email": "john@example.com"})
|
||||
print(f"Deleted {result.deleted_count} user")
|
||||
|
||||
# Delete multiple documents
|
||||
count = mongodb.delete_many(
|
||||
database="store_db", collection="products", filter_query={"stock": 0}
|
||||
)
|
||||
print(f"Deleted {count} out-of-stock products")
|
||||
result = products_collection.delete_many({"stock": 0})
|
||||
print(f"Deleted {result.deleted_count} out-of-stock products")
|
||||
|
||||
|
||||
def aggregate_examples() -> None:
|
||||
"""Examples of aggregation operations."""
|
||||
@MongoDBHandler.with_mongodb
|
||||
def aggregate_examples(db) -> None:
|
||||
"""Examples of aggregate operations."""
|
||||
# Get the collection
|
||||
products_collection = db.get_collection("products")
|
||||
|
||||
# Calculate average price by category
|
||||
pipeline = [
|
||||
{
|
||||
@@ -116,21 +107,23 @@ def aggregate_examples() -> None:
|
||||
},
|
||||
{"$sort": {"avg_price": -1}},
|
||||
]
|
||||
results = mongodb.aggregate(
|
||||
database="store_db", collection="products", pipeline=pipeline
|
||||
)
|
||||
results = products_collection.aggregate(pipeline)
|
||||
print("Category statistics:", list(results))
|
||||
|
||||
|
||||
def complex_query_example() -> None:
|
||||
"""Example of a complex query combining multiple operations."""
|
||||
@MongoDBHandler.with_mongodb
|
||||
def complex_query_example(db) -> None:
|
||||
"""Example of a more complex query combining multiple operations."""
|
||||
# Get the collection
|
||||
users_collection = db.get_collection("users")
|
||||
|
||||
# Find active users who made purchases in last 30 days
|
||||
pipeline = [
|
||||
{
|
||||
"$match": {
|
||||
"status": "active",
|
||||
"last_purchase": {
|
||||
"$gte": datetime.utcnow().replace(day=datetime.utcnow().day - 30)
|
||||
"$gte": arrow.now().shift(days=-30).datetime,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -152,9 +145,7 @@ def complex_query_example() -> None:
|
||||
},
|
||||
{"$sort": {"total_spent": -1}},
|
||||
]
|
||||
results = mongodb.aggregate(
|
||||
database="user_db", collection="users", pipeline=pipeline
|
||||
)
|
||||
results = users_collection.aggregate(pipeline)
|
||||
print("Active users with recent purchases:", list(results))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user