DetectifAI-Backend / DetectifAI_db /database_setup.py
blacksinisterx's picture
fix: keyframe images, video clips, evidence images, live stream webcam+URL, remove demo mode
fd50325 verified
from pymongo import MongoClient, ASCENDING
import os
from dotenv import load_dotenv
load_dotenv()
MONGO_URI = os.getenv("MONGO_URI")
client = MongoClient(MONGO_URI)
db = client.get_default_database()
def create_collection_if_not_exists(name, validator=None, indexes=None):
"""Create collection if it doesn't exist, otherwise skip"""
try:
if validator:
db.create_collection(name, validator=validator)
else:
db.create_collection(name)
print(f"Created collection: {name}")
except Exception as e:
if "already exists" in str(e):
print(f"Collection {name} already exists, skipping...")
else:
print(f"Error creating collection {name}: {e}")
return False
# Create indexes if specified
if indexes:
for index in indexes:
try:
if isinstance(index, tuple):
# Index with options
db[name].create_index(index[0], **index[1])
else:
# Simple index
db[name].create_index(index)
print(f" Created index on {name}")
except Exception as e:
if "already exists" in str(e) or "duplicate key" in str(e):
print(f" Index on {name} already exists")
else:
print(f" Error creating index on {name}: {e}")
return True
# === ADMIN ===
create_collection_if_not_exists("admin", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["admin_id", "username", "email", "password"],
"properties": {
"admin_id": {"bsonType": "string"},
"username": {"bsonType": "string"},
"email": {"bsonType": "string"},
"password": {"bsonType": "string"},
"role": {"bsonType": "string"},
"created_at": {"bsonType": "date"},
"updated_at": {"bsonType": "date"},
"last_login": {"bsonType": ["date", "null"]}
}
}
}, indexes=[([("email", ASCENDING)], {"unique": True}), "username"])
# === USERS ===
create_collection_if_not_exists("users", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["user_id", "email"],
"properties": {
"user_id": {"bsonType": "string"},
"username": {"bsonType": "string"},
"email": {"bsonType": "string"},
"password_hash": {"bsonType": "string"},
"role": {"bsonType": "string"},
"profile_data": {"bsonType": "object"},
"is_active": {"bsonType": "bool"},
"created_at": {"bsonType": "date"},
"updated_at": {"bsonType": "date"},
"last_login": {"bsonType": ["date", "null"]}
}
}
}, indexes=[([("email", ASCENDING)], {"unique": True}), "username"])
# === VIDEO FILES ===
create_collection_if_not_exists("video_files", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["video_id", "user_id", "file_path"],
"properties": {
"video_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"file_path": {"bsonType": "string"},
"minio_object_key": {"bsonType": "string"},
"minio_bucket": {"bsonType": "string"},
"codec": {"bsonType": "string"},
"fps": {"bsonType": "double"},
"upload_date": {"bsonType": "date"},
"duration_secs": {"bsonType": "int"},
"file_size_bytes": {"bsonType": "long"},
"meta_data": {"bsonType": "object"}
}
}
}, indexes=["user_id", "upload_date"])
# === EVENTS ===
create_collection_if_not_exists("events", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["event_id", "video_id", "start_timestamp_ms", "end_timestamp_ms"],
"properties": {
"event_id": {"bsonType": "string"},
"video_id": {"bsonType": "string"},
"start_timestamp_ms": {"bsonType": "long"},
"end_timestamp_ms": {"bsonType": "long"},
"confidence_score": {"bsonType": "double"},
"is_verified": {"bsonType": "bool"},
"is_false_positive": {"bsonType": "bool"},
"verified_at": {"bsonType": ["date", "null"]},
"verified_by": {"bsonType": ["string", "null"]},
"visual_embedding": {"bsonType": "array"},
"bounding_boxes": {"bsonType": "object"},
"event_type": {"bsonType": "string"}
}
}
}, indexes=["video_id", "event_type", "is_verified"])
# === EVENT CLIPS ===
create_collection_if_not_exists("event_clips", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["clip_id", "event_id", "clip_path"],
"properties": {
"clip_id": {"bsonType": "string"},
"event_id": {"bsonType": "string"},
"clip_path": {"bsonType": "string"},
"thumbnail_path": {"bsonType": "string"},
"minio_object_key": {"bsonType": "string"},
"minio_bucket": {"bsonType": "string"},
"duration_ms": {"bsonType": "long"},
"extracted_at": {"bsonType": "date"},
"file_size_bytes": {"bsonType": "long"}
}
}
}, indexes=["event_id"])
# === DETECTED FACES ===
create_collection_if_not_exists("detected_faces", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["face_id", "event_id", "detected_at"],
"properties": {
"face_id": {"bsonType": "string"},
"event_id": {"bsonType": "string"},
"detected_at": {"bsonType": "date"},
"confidence_score": {"bsonType": "double"},
"face_embedding": {"bsonType": "array"},
"minio_object_key": {"bsonType": "string"},
"minio_bucket": {"bsonType": "string"},
"face_image_path": {"bsonType": "string"},
"bounding_boxes": {"bsonType": "object"}
}
}
}, indexes=["event_id", "detected_at"])
# === FACE MATCHES ===
create_collection_if_not_exists("face_matches", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["match_id", "face_id_1", "face_id_2", "similarity_score"],
"properties": {
"match_id": {"bsonType": "string"},
"face_id_1": {"bsonType": "string"},
"face_id_2": {"bsonType": "string"},
"similarity_score": {"bsonType": "double"},
"matched_at": {"bsonType": "date"}
}
}
}, indexes=["face_id_1", "face_id_2", "similarity_score"])
# === EVENT DESCRIPTIONS ===
create_collection_if_not_exists("event_descriptions", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["description_id", "event_id", "text_embedding"],
"properties": {
"description_id": {"bsonType": "string"},
"event_id": {"bsonType": "string"},
"text_embedding": {"bsonType": "array"},
"caption": {"bsonType": "string"},
"confidence": {"bsonType": "double"},
"created_at": {"bsonType": "date"},
"updated_at": {"bsonType": "date"}
}
}
}, indexes=["event_id", "created_at"])
# === EVENT CAPTIONS ===
create_collection_if_not_exists("event_captions", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["description_id", "description"],
"properties": {
"description_id": {"bsonType": "string"},
"description": {"bsonType": "string"}
}
}
}, indexes=["description_id"])
# === QUERY ===
create_collection_if_not_exists("query", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["query_id", "user_id", "query_text"],
"properties": {
"query_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"query_text": {"bsonType": "string"},
"query_embedding": {"bsonType": "array"},
"executed_at": {"bsonType": "date"}
}
}
}, indexes=["user_id", "executed_at"])
# === QUERY RESULT ===
create_collection_if_not_exists("query_result", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["result_id", "query_id", "event_id"],
"properties": {
"result_id": {"bsonType": "string"},
"query_id": {"bsonType": "string"},
"event_id": {"bsonType": "string"},
"relevance_score": {"bsonType": "double"},
"match_details": {"bsonType": "object"},
"returned_at": {"bsonType": "date"}
}
}
}, indexes=["query_id", "event_id", "relevance_score"])
# === SUBSCRIPTION PLANS ===
create_collection_if_not_exists("subscription_plans", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["plan_id", "plan_name", "price"],
"properties": {
"plan_id": {"bsonType": "string"},
"plan_name": {"bsonType": "string"},
"description": {"bsonType": "string"},
"price": {"bsonType": "decimal"},
"features": {"bsonType": "string"},
"storage_limit": {"bsonType": "int"},
"is_active": {"bsonType": "bool"},
"stripe_product_id": {"bsonType": "string"},
"stripe_price_ids": {"bsonType": "object"},
"billing_periods": {"bsonType": "array"},
"created_at": {"bsonType": "date"},
"updated_at": {"bsonType": "date"}
}
}
}, indexes=[([("plan_id", ASCENDING)], {"unique": True}), "is_active", "stripe_product_id"])
# === USER SUBSCRIPTIONS ===
create_collection_if_not_exists("user_subscriptions", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["subscription_id", "user_id", "plan_id"],
"properties": {
"subscription_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"plan_id": {"bsonType": "string"},
"start_date": {"bsonType": "date"},
"end_date": {"bsonType": "date"},
"stripe_customer_id": {"bsonType": "string"},
"stripe_subscription_id": {"bsonType": "string"},
"billing_period": {"bsonType": "string"},
"status": {"bsonType": "string"},
"current_period_start": {"bsonType": "date"},
"current_period_end": {"bsonType": "date"},
"cancel_at_period_end": {"bsonType": "bool"},
"created_at": {"bsonType": "date"},
"updated_at": {"bsonType": "date"}
}
}
}, indexes=["user_id", "plan_id", "start_date", "stripe_customer_id", "stripe_subscription_id", "status"])
# === SUBSCRIPTION EVENTS === (NEW - for audit trail)
create_collection_if_not_exists("subscription_events", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["event_id", "subscription_id", "event_type"],
"properties": {
"event_id": {"bsonType": "string"},
"subscription_id": {"bsonType": "string"},
"event_type": {"bsonType": "string"},
"stripe_event_id": {"bsonType": "string"},
"event_data": {"bsonType": "object"},
"created_at": {"bsonType": "date"}
}
}
}, indexes=["subscription_id", "event_type", "created_at", "stripe_event_id"])
# === PAYMENT HISTORY === (NEW - for transaction records)
create_collection_if_not_exists("payment_history", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["payment_id", "user_id", "amount"],
"properties": {
"payment_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"stripe_payment_intent_id": {"bsonType": "string"},
"amount": {"bsonType": "double"},
"currency": {"bsonType": "string"},
"status": {"bsonType": "string"},
"payment_method": {"bsonType": "string"},
"created_at": {"bsonType": "date"}
}
}
}, indexes=["user_id", "created_at", "status", "stripe_payment_intent_id"])
# === SUBSCRIPTION USAGE === (NEW - for analytics and limits)
create_collection_if_not_exists("subscription_usage", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["usage_id", "user_id", "usage_type"],
"properties": {
"usage_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"usage_type": {"bsonType": "string"},
"usage_value": {"bsonType": "double"},
"usage_date": {"bsonType": "date"},
"created_at": {"bsonType": "date"}
}
}
}, indexes=["user_id", "usage_type", "usage_date"])
# === USER SESSIONS ===
create_collection_if_not_exists("user_sessions", validator={
"$jsonSchema": {
"bsonType": "object",
"required": ["session_id", "user_id", "session_token", "expires_at"],
"properties": {
"session_id": {"bsonType": "string"},
"user_id": {"bsonType": "string"},
"session_token": {"bsonType": "string"},
"expires_at": {"bsonType": "date"},
"ip_address": {"bsonType": "string"},
"user_agent": {"bsonType": "string"},
"created_at": {"bsonType": "date"}
}
}
}, indexes=[
([("session_token", ASCENDING)], {"unique": True}),
"user_id",
"expires_at"
])
print("\nDatabase schema setup completed successfully.")
print("All collections are ready with validation and indexes.")