mongollect
mongollect is a tiny, zero-dependency Python utility that lets you inject MongoDB collections into your classes using decorators.
🚀 Features
✅ Simple @injector.collection("name") decorator for single collections
✅ @injector.multiple_collections() decorator for multiple collections
✅ Keeps your services clean — no repeated DB connection logic
✅ Lets you control the MongoDB connection (great for FastAPI, Flask, etc.)
✅ Easy to test and mock
✅ Early validation of collection existence
✅ Full type hint support
💻 Installation
pip install mongollect
⚡ Quick Start
Single Collection Injection
from pymongo import MongoClient
from mongollect import CollectionInjector
# Set up your MongoDB connection
client = MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
# Create the injector
injector = CollectionInjector(db)
# Apply to your service
@injector.collection("accounts")
class AccountService:
def create(self, data):
return self.collection.insert_one(data)
def find_all(self):
return list(self.collection.find())
# Example usage
service = AccountService()
service.create({"username": "john_doe", "email": "john@example.com"})
print(service.find_all())
Multiple Collections Injection
# Inject multiple collections into a single class
@injector.multiple_collections(
users="users",
orders="orders",
products="products"
)
class CommerceService:
def get_user_orders(self, user_id):
# Access collections via their attribute names
user = self.users.find_one({"_id": user_id})
orders = list(self.orders.find({"user_id": user_id}))
return {"user": user, "orders": orders}
def get_order_details(self, order_id):
order = self.orders.find_one({"_id": order_id})
if order:
# Enrich with product details
product_ids = [item["product_id"] for item in order.get("items", [])]
products = list(self.products.find({"_id": {"$in": product_ids}}))
order["product_details"] = products
return order
# Example usage
commerce = CommerceService()
user_orders = commerce.get_user_orders("user123")
order_details = commerce.get_order_details("order456")
🛠 API Reference
CollectionInjector(db)
Create an injector with your MongoDB database instance.
Parameters:
db→ Apymongo.database.Databaseinstance
Raises:
ValueError→ If db is None
@injector.collection(name)
A class decorator that injects a single MongoDB collection into self.collection.
Parameters:
name→ The MongoDB collection name (string)
Raises:
ValueError→ If collection name is empty or not a stringKeyError→ If the specified collection doesn't exist in the databaseTypeError→ If decorator is not applied to a class
Example:
@injector.collection("users")
class UserService:
def find_user(self, user_id):
return self.collection.find_one({"_id": user_id})
@injector.multiple_collections(**collections)
A class decorator that injects multiple MongoDB collections as named attributes.
Parameters:
**collections→ Keyword arguments where keys are attribute names and values are collection names
Raises:
ValueError→ If no collections are specifiedKeyError→ If any specified collection doesn't exist in the databaseTypeError→ If decorator is not applied to a class
Example:
@injector.multiple_collections(
users="user_collection",
posts="post_collection",
comments="comment_collection"
)
class BlogService:
def get_user_posts_with_comments(self, user_id):
user = self.users.find_one({"_id": user_id})
posts = list(self.posts.find({"author_id": user_id}))
for post in posts:
post["comments"] = list(
self.comments.find({"post_id": post["_id"]})
)
return {"user": user, "posts": posts}
🎯 Advanced Usage
Custom Attribute Names
When using multiple_collections, you can map collections to custom attribute names:
@injector.multiple_collections(
user_db="users", # self.user_db -> "users" collection
order_db="orders", # self.order_db -> "orders" collection
inventory="products" # self.inventory -> "products" collection
)
class ECommerceService:
def process_order(self, order_data):
# Use custom attribute names
user = self.user_db.find_one({"_id": order_data["user_id"]})
product = self.inventory.find_one({"_id": order_data["product_id"]})
if user and product:
return self.order_db.insert_one(order_data)
Error Handling
The decorators validate collections at decoration time, not runtime:
# This will raise KeyError immediately when the decorator is applied
try:
@injector.collection("nonexistent_collection")
class BadService:
pass
except KeyError as e:
print(f"Collection validation failed: {e}")
✅ Why use mongollect?
- Clean Architecture: Keeps your service layer clean and DRY
- Flexible: Works with any MongoDB database you set up
- Testable: Easy to inject mock databases for testing
- Type Safe: Full type hint support for better IDE experience
- Early Validation: Catches collection errors at decoration time
- Lightweight: Zero dependencies beyond Python standard library
- Multiple Collections: Handle complex services that need multiple collections
📄 License
MIT — do whatever you want, just give credit!
Metadata
Release files for mongollect 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mongollect-0.1.0.tar.gz | 6.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mongollect-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.2 kB
Release files / mongollect-0.1.0.tar.gz
| Download URL | mongollect-0.1.0.tar.gz |
|---|---|
| Size | 6.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b851f45c1ac99389ec119546f8a3c0627868c6d9573cfa616219a2f320fa3a35
|
|
BLAKE2b-256 checksum How to use checksums |
cd4d639d81ed1e8a01a6ab8667b17eb9d075b68dbf43de058aff09d2d6ed3782
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.6
|
Release files / mongollect-0.1.0-py3-none-any.whl
| Download URL | mongollect-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
637c867184a4502f3feb7eb317b3cfa6cc1d98a6f17ae330d6ec79edeab5bb0a
|
|
BLAKE2b-256 checksum How to use checksums |
adeabc1b0362e645b9cd09441a43809365b81cfb899197d90d26b65aeb6d33d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.6
|