from motor.motor_asyncio import AsyncIOMotorClient
from bson import ObjectId
from typing import List, Dict, Any
from threading import Lock
class MongoDBClient:
_instance = None
_lock: Lock = Lock()
def __new__(cls, *args, **kwargs):
if not cls._instance:
with cls._lock:
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, uri: str, db_name: str, username: str = None, password: str = None):
if not hasattr(self, "initialized"):
self.uri = uri
self.db_name = db_name
self.username = username
self.password = password
self.client = None
self.db = None
self.initialized = True
async def connect(self):
if self.client is None:
self.client = AsyncIOMotorClient(
self.uri,
username=self.username,
password=self.password,
maxPoolSize=20, # Example pool size
minPoolSize=5
)
self.db = self.client[self.db_name]
async def insert_one(self, collection_name: str, document: Dict[str, Any]):
collection = self.db[collection_name]
result = await collection.insert_one(document)
return str(result.inserted_id)
async def find_one(self, collection_name: str, query: Dict[str, Any]):
collection = self.db[collection_name]
document = await collection.find_one(query)
if document:
document["_id"] = str(document["_id"])
return document
async def update_one(self, collection_name: str, query: Dict[str, Any], update: Dict[str, Any]):
collection = self.db[collection_name]
result = await collection.update_one(query, {"$set": update})
return result.modified_count
async def delete_one(self, collection_name: str, query: Dict[str, Any]):
collection = self.db[collection_name]
result = await collection.delete_one(query)
return result.deleted_count
async def find_many(self, collection_name: str, query: Dict[str, Any], limit: int = 100):
collection = self.db[collection_name]
cursor = collection.find(query).limit(limit)
results = []
async for document in cursor:
document["_id"] = str(document["_id"])
results.append(document)
return results
async def update_many(self, collection_name: str, query: Dict[str, Any], update: Dict[str, Any]):
collection = self.db[collection_name]
result = await collection.update_many(query, {"$set": update})
return result.modified_count
async def delete_many(self, collection_name: str, query: Dict[str, Any]):
collection = self.db[collection_name]
result = await collection.delete_many(query)
return result.deleted_count
服务中使用示例:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Dict, Any
import uvicorn
app = FastAPI()
class MongoDBSettings:
MONGO_URI = "your_mongo_uri"
MONGO_DB_NAME = "your_db_name"
MONGO_USER = "your_username"
MONGO_PASSWORD = "your_password"
mongodb_settings = MongoDBSettings()
mongodb_client = MongoDBClient(
mongodb_settings.MONGO_URI,
mongodb_settings.MONGO_DB_NAME,
mongodb_settings.MONGO_USER,
mongodb_settings.MONGO_PASSWORD
)
@app.on_event("startup")
async def startup_clients():
await mongodb_client.connect()
@app.on_event("shutdown")
async def shutdown_clients():
mongodb_client.client.close()
class User(BaseModel):
name: str
email: str
class UserUpdate(BaseModel):
name: str = None
email: str = None
class Item(BaseModel):
key: str
value: Any
class Items(BaseModel):
items: Dict[str, Any]
@app.post("/mongodb/", response_model=Dict[str, Any])
async def create_user(user: User):
user_id = await mongodb_client.insert_one("users", user.dict())
return {"id": user_id}
@app.get("/mongodb/{user_id}", response_model=Dict[str, Any])
async def get_user(user_id: str):
user = await mongodb_client.find_one("users", {"_id": ObjectId(user_id)})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.put("/mongodb/{user_id}", response_model=Dict[str, Any])
async def update_user(user_id: str, user: UserUpdate):
update_data = {k: v for k, v in user.dict().items() if v is not None}
if not update_data:
raise HTTPException(status_code=400, detail="No fields to update")
modified_count = await mongodb_client.update_one("users", {"_id": ObjectId(user_id)}, update_data)
if modified_count == 0:
raise HTTPException(status_code=404, detail="User not found or no changes made")
return {"status": "User updated"}
@app.put("/mongodb/", response_model=Dict[str, Any])
async def update_users(users: List[UserUpdate]):
for user in users:
user_id = user.dict().get("id")
if user_id:
update_data = {k: v for k, v in user.dict().items() if v is not None}
if update_data:
await mongodb_client.update_one("users", {"_id": ObjectId(user_id)}, update_data)
return {"status": "Users updated"}
@app.delete("/mongodb/{user_id}", response_model=Dict[str, Any])
async def delete_user(user_id: str):
deleted_count = await mongodb_client.delete_one("users", {"_id": ObjectId(user_id)})
if deleted_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return {"status": "User deleted"}
@app.delete("/mongodb/", response_model=Dict[str, Any])
async def delete_users(user_ids: List[str]):
await mongodb_client.delete_many("users", {"_id": {"$in": [ObjectId(user_id) for user_id in user_ids]}})
return {"status": "Users deleted"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)