7.2 KiB
7.2 KiB
ZEE Quiz Application - Database Schema
app_ver: 1.0.0 doc_ver: A1
Database Schema
1. Primary Database (PostgreSQL 14)
- DB Type: Relational
- Technology: PostgreSQL 14
- Purpose: Primary data store for all application data
- Connection String:
postgresql://user:password@host:5432/zee_quiz
Tables
1.1. users
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'user',
is_active BOOLEAN DEFAULT true,
last_login_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);
1.2. profiles
CREATE TABLE profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
date_of_birth DATE NOT NULL,
gender VARCHAR(20) NOT NULL,
preferred_gender VARCHAR(20) NOT NULL,
phone_number VARCHAR(20),
facebook_link VARCHAR(255),
location VARCHAR(100),
team VARCHAR(50),
hobbies TEXT[],
things_not_tried TEXT,
hopes_for_partner TEXT,
dealbreakers TEXT,
message_to_partner TEXT,
zodiac_sign VARCHAR(20),
access_code VARCHAR(20) UNIQUE,
personal_link VARCHAR(255),
is_lucky_winner BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_profiles_user_id ON profiles(user_id);
CREATE INDEX idx_profiles_access_code ON profiles(access_code);
1.3. photos
CREATE TABLE photos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id UUID REFERENCES profiles(id) ON DELETE CASCADE,
url VARCHAR(512) NOT NULL,
is_primary BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_photos_profile_id ON photos(profile_id);
1.4. quizzes
CREATE TABLE quizzes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255) NOT NULL,
description TEXT,
start_time TIMESTAMP WITH TIME ZONE NOT NULL,
end_time TIMESTAMP WITH TIME ZONE NOT NULL,
time_limit_seconds INT DEFAULT 300, -- 5 minutes
is_active BOOLEAN DEFAULT true,
created_by UUID REFERENCES users(id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_quizzes_active ON quizzes(is_active, start_time, end_time);
1.5. questions
CREATE TABLE questions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE,
question_text TEXT NOT NULL,
question_type VARCHAR(50) NOT NULL, -- multiple_choice, true_false, short_answer
options JSONB,
correct_answer TEXT,
points INT DEFAULT 1,
display_order INT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_questions_quiz_id ON questions(quiz_id);
1.6. user_answers
CREATE TABLE user_answers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE,
question_id UUID REFERENCES questions(id) ON DELETE CASCADE,
answer_text TEXT,
is_correct BOOLEAN,
points_earned INT DEFAULT 0,
time_taken_seconds INT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Indexes
CREATE INDEX idx_user_answers_user_quiz ON user_answers(user_id, quiz_id);
CREATE INDEX idx_user_answers_question ON user_answers(question_id);
2. Cache (Redis 7)
- DB Type: Key-Value
- Technology: Redis 7
- Purpose: Caching, rate limiting, and session storage
- Connection String:
redis://:password@host:6379/0
Key Patterns
user:sessions:{session_id}- User session dataquiz:leaderboard:{quiz_id}- Sorted set for quiz leaderboardrate_limit:{ip_address}- Rate limiting countersuser:profile:{user_id}- Cached user profile dataquiz:active- Set of active quiz IDs
3. File Storage (AWS S3)
- DB Type: Object Storage
- Technology: AWS S3
- Purpose: Storing user-uploaded files (profile photos, quiz images)
- Bucket Name:
zee-quiz-{environment}
Directory Structure
zquiz/
├── profiles/
│ └── {user_id}/
│ ├── {photo_id}.jpg
│ └── {photo_id}_thumbnail.jpg
└── quizzes/
└── {quiz_id}/
└── {question_id}.{ext}
Data Structures
1. User Session
type UserSession struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Email string `json:"email"`
Role string `json:"role"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
LastActivity time.Time `json:"last_activity"`
ExpiresAt time.Time `json:"expires_at"`
}
2. Quiz Question
type Question struct {
ID string `json:"id"`
QuizID string `json:"quiz_id"`
QuestionText string `json:"question_text"`
QuestionType string `json:"question_type"` // multiple_choice, true_false, short_answer
Options []string `json:"options,omitempty"`
CorrectAnswer string `json:"correct_answer,omitempty"`
Points int `json:"points"`
DisplayOrder int `json:"display_order"`
MediaURL string `json:"media_url,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
3. Quiz Result
type QuizResult struct {
UserID string `json:"user_id"`
QuizID string `json:"quiz_id"`
TotalQuestions int `json:"total_questions"`
CorrectAnswers int `json:"correct_answers"`
TotalPoints int `json:"total_points"`
Score float64 `json:"score"` // Percentage
TimeCompleted time.Time `json:"time_completed"`
Rank int `json:"rank,omitempty"`
}
Database Migrations
Initial Migration (0001_initial.up.sql)
-- This file is auto-generated and managed by the golang-migrate tool
-- It contains all the initial table creation statements
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Create users table
-- (Include all table creation SQL from above)
Performance Considerations
Indexing Strategy
- All foreign keys are indexed
- Frequently queried columns have appropriate indexes
- Composite indexes for common query patterns
Partitioning
- User answers table is partitioned by
quiz_idfor large-scale deployments - Old quiz data can be archived to cold storage
Caching Strategy
- User sessions and active quiz data are cached in Redis
- Leaderboards are maintained in Redis sorted sets
- Profile data is cached with TTL
Document Version: A1 Last Updated: 2025-06-06