Database Schema
Complete data models and relationships in SophieAI
Database Schema
SophieAI uses PostgreSQL with Prisma ORM for data management. This document outlines all models, relationships, and database structure.
Database Technology: PostgreSQL 14+ with Prisma ORM for type-safe database access and migrations.
Quick Database Setup
Install Dependencies
# Using Homebrew
brew install postgresql
brew services start postgresql
# Verify installation
psql --version# Install PostgreSQL
sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Verify installation
psql --version# Run PostgreSQL in Docker
docker run --name sophieai-postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=sophieai \
-p 5432:5432 \
-d postgres:14
# Verify container is running
docker ps | grep sophieai-postgresCreate Database
CREATE DATABASE sophieai;
CREATE USER sophieai_user WITH PASSWORD 'your_secure_password';
GRANT ALL PRIVILEGES ON DATABASE sophieai TO sophieai_user;
-- Enable required extensions
\c sophieai
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";# Connect to Docker PostgreSQL
docker exec -it sophieai-postgres psql -U postgres -d sophieai
# Enable extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";Extensions Required: The uuid-ossp extension is needed for UUID generation, and pg_trgm is required for full-text search capabilities.
Configure Environment
Set your database URL in the .env file:
DATABASE_URL="postgresql://sophieai_user:your_secure_password@localhost:5432/sophieai"Security: Use strong passwords in production and consider using connection pooling for better performance.
Run Migrations
Apply the database schema:
# Generate Prisma client
bunx prisma generate
# Apply migrations
bunx prisma migrate dev
# Seed database (optional)
bunx prisma db seedVerification: Run bunx prisma studio to open the database browser and verify your schema.
Database Models Overview
Primary Entity Models:
- User: Authentication and user management
- Course: Academic course organization
- Note: Notes with transcription support
- Document: File uploads and processing
These models form the foundation of the SophieAI platform and contain the primary user data.
AI-Generated Content:
- FlashcardSet: Flashcard collections
- Flashcard: Individual flashcards
- Quiz: Quiz containers with metadata
- Question: Individual quiz questions
- StudyGuide: AI-generated study materials
These models store AI-generated educational content based on user notes and documents.
Platform Features:
- ChatSession: AI chat conversations
- ChatMessage: Individual chat messages
- CalendarEvent: Calendar integration
- ImportJob: Background job tracking
- Notification: User notifications
These models support platform features and system operations.
Key Relationships:
- Users own all content (cascading deletes)
- Courses organize related content
- Study materials link to source notes/documents
- Chat sessions can be course-specific
- Jobs track async operations
All models follow consistent relationship patterns for data integrity.
Core Models
Study Materials Models
FlashcardSet Model:
model FlashcardSet {
id String @id @default(cuid())
title String
description String?
difficulty Difficulty
tags String[] @default([])
color String @default("blue")
userId String
courseId String?
noteId String?
documentId String?
// Relationships
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
note Note? @relation(fields: [noteId], references: [id], onDelete: SetNull)
document Document? @relation(fields: [documentId], references: [id], onDelete: SetNull)
flashcards Flashcard[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Individual Flashcard:
model Flashcard {
id String @id @default(cuid())
question String
answer String
hint String?
explanation String?
difficulty Difficulty
flashcardSetId String
flashcardSet FlashcardSet @relation(fields: [flashcardSetId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Quiz Container:
model Quiz {
id String @id @default(cuid())
title String
description String?
difficulty Difficulty
timeLimit Int?
totalPoints Int
userId String
courseId String?
noteId String?
documentId String?
// Relationships
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
note Note? @relation(fields: [noteId], references: [id], onDelete: SetNull)
document Document? @relation(fields: [documentId], references: [id], onDelete: SetNull)
questions Question[]
quizResponses QuizResponse[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Question Model:
model Question {
id String @id @default(cuid())
type QuestionType
question String
options String?
correctAnswer String
explanation String?
hint String?
difficulty Difficulty
points Int
quizId String
quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}StudyGuide Model:
model StudyGuide {
id String @id @default(cuid())
title String
content String
noteId String?
courseId String?
documentId String?
userId String
// Relationships
note Note? @relation(fields: [noteId], references: [id], onDelete: SetNull)
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
document Document? @relation(fields: [documentId], references: [id], onDelete: SetNull)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Features:
- AI-generated comprehensive study materials
- Links to source notes or documents
- Rich text content support
- Course association for organization
AI Generation: All study materials are automatically generated from source content using AI models, with manual editing capabilities.
System Models
ChatSession Model:
model ChatSession {
id String @id @default(cuid())
title String
courseId String?
userId String
// Relationships
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
messages ChatMessage[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}ChatMessage Model:
model ChatMessage {
id String @id @default(cuid())
content String
messageType MessageType
references String?
chatSessionId String
chatSession ChatSession @relation(fields: [chatSessionId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}CalendarEvent Model:
model CalendarEvent {
id String @id @default(cuid())
title String
description String?
startDate DateTime
endDate DateTime?
eventType EventType
location String?
priority Priority?
color String
googleEventId String?
googleCalendarId String?
courseId String?
documentId String?
userId String
// Relationships
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
document Document? @relation(fields: [documentId], references: [id], onDelete: SetNull)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Features:
- Google Calendar synchronization
- Multiple event types (assignments, exams, lectures)
- Priority levels and color coding
- Auto-generation from documents (syllabi)
ImportJob Model:
model ImportJob {
id String @id @default(cuid())
source ImportSource
sourceUrl String?
title String?
status JobStatus
progress Int
errorMessage String?
completedAt DateTime?
userId String
noteId String? @unique
// Relationships
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
note Note? @relation(fields: [noteId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Job Processing:
- File upload processing
- YouTube video transcription
- Audio file conversion
- Progress tracking and error handling
Session Model:
model Session {
id String @id @default(cuid())
expiresAt DateTime
token String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ipAddress String?
userAgent String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}Account Model:
model Account {
id String @id @default(cuid())
accountId String
providerId String
userId String
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([providerId, accountId])
}Enums and Types
Database Relationships
Relationship Patterns: The schema follows consistent patterns with cascading deletes for user-owned content and null set for optional associations.
Core Relationships
- User owns all content with cascading deletes
- Course serves as organizational container
- Notes and Documents are source material for AI generation
- Study materials link back to their source content
Data Integrity Features
- Foreign Key Constraints: Ensure referential integrity
- Cascading Deletes: Clean up orphaned records
- Unique Constraints: Prevent duplicate data
- Null Set Relations: Preserve data when optional relations are removed
Search and Indexing
The database includes specialized models for search functionality:
model DocumentSearchIndex {
id String @id @default(cuid())
documentId String
content String
pageNumber Int?
chunkIndex Int
embedding String?
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Database Complete: This schema supports the full SophieAI platform with AI-powered features, file processing, search capabilities, and integrated study tools.