Files
tasteby/backend/sql/schema.sql
joungmin 36bec10bd0 Initial commit: Tasteby - YouTube restaurant map service
Backend (FastAPI + Oracle ADB), Frontend (Next.js), daemon worker.
Features: channel/video/restaurant management, semantic search,
Google OAuth, user reviews.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:47:19 +09:00

128 lines
5.5 KiB
MySQL

-- Tasteby: Oracle ADB (23ai) Schema
-- Run against Oracle ADB before starting the backend.
-- 1. channels
CREATE TABLE channels (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
channel_id VARCHAR2(50) NOT NULL,
channel_name VARCHAR2(200) NOT NULL,
channel_url VARCHAR2(500),
is_active NUMBER(1) DEFAULT 1 NOT NULL,
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_channels PRIMARY KEY (id),
CONSTRAINT uq_channels_cid UNIQUE (channel_id)
);
-- 2. videos
CREATE TABLE videos (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
channel_id VARCHAR2(36) NOT NULL,
video_id VARCHAR2(20) NOT NULL,
title VARCHAR2(500) NOT NULL,
url VARCHAR2(500) NOT NULL,
published_at TIMESTAMP,
transcript_text CLOB,
status VARCHAR2(20) DEFAULT 'pending' NOT NULL,
processed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_videos PRIMARY KEY (id),
CONSTRAINT uq_videos_vid UNIQUE (video_id),
CONSTRAINT fk_videos_channel FOREIGN KEY (channel_id) REFERENCES channels(id),
CONSTRAINT ck_videos_status CHECK (status IN ('pending','processing','done','error'))
);
-- 3. restaurants
CREATE TABLE restaurants (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
name VARCHAR2(200) NOT NULL,
address VARCHAR2(500),
region VARCHAR2(100),
latitude NUMBER(10,7),
longitude NUMBER(10,7),
cuisine_type VARCHAR2(100),
price_range VARCHAR2(50),
phone VARCHAR2(50),
website VARCHAR2(500),
google_place_id VARCHAR2(200),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_restaurants PRIMARY KEY (id)
);
-- 4. video_restaurants (N:M)
CREATE TABLE video_restaurants (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
video_id VARCHAR2(36) NOT NULL,
restaurant_id VARCHAR2(36) NOT NULL,
foods_mentioned CLOB,
evaluation CLOB,
guests CLOB,
air_date DATE,
citation_text CLOB,
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_video_restaurants PRIMARY KEY (id),
CONSTRAINT fk_vr_video FOREIGN KEY (video_id) REFERENCES videos(id),
CONSTRAINT fk_vr_restaurant FOREIGN KEY (restaurant_id) REFERENCES restaurants(id),
CONSTRAINT uq_vr_video_rest UNIQUE (video_id, restaurant_id)
);
-- JSON check constraints for CLOB JSON columns
-- (Oracle 23ai supports IS JSON on CLOB)
ALTER TABLE video_restaurants ADD CONSTRAINT ck_vr_foods CHECK (foods_mentioned IS JSON);
ALTER TABLE video_restaurants ADD CONSTRAINT ck_vr_eval CHECK (evaluation IS JSON);
ALTER TABLE video_restaurants ADD CONSTRAINT ck_vr_guests CHECK (guests IS JSON);
-- 5. tasteby_users (NOT "users" — that table belongs to another project)
CREATE TABLE tasteby_users (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
provider VARCHAR2(20) NOT NULL,
provider_id VARCHAR2(200) NOT NULL,
email VARCHAR2(200),
nickname VARCHAR2(100),
avatar_url VARCHAR2(500),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
last_login_at TIMESTAMP,
CONSTRAINT pk_tasteby_users PRIMARY KEY (id),
CONSTRAINT uq_tasteby_users_provider UNIQUE (provider, provider_id),
CONSTRAINT ck_tasteby_users_provider CHECK (provider IN ('google','apple'))
);
-- 6. user_reviews
CREATE TABLE user_reviews (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
user_id VARCHAR2(36) NOT NULL,
restaurant_id VARCHAR2(36) NOT NULL,
rating NUMBER(2,1) NOT NULL,
review_text CLOB,
visited_at DATE,
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_user_reviews PRIMARY KEY (id),
CONSTRAINT fk_ur_user FOREIGN KEY (user_id) REFERENCES tasteby_users(id),
CONSTRAINT fk_ur_restaurant FOREIGN KEY (restaurant_id) REFERENCES restaurants(id),
CONSTRAINT ck_ur_rating CHECK (rating BETWEEN 0.5 AND 5.0)
);
-- 7. restaurant_vectors (semantic search)
CREATE TABLE restaurant_vectors (
id VARCHAR2(36) DEFAULT SYS_GUID() NOT NULL,
restaurant_id VARCHAR2(36) NOT NULL,
chunk_text CLOB NOT NULL,
embedding VECTOR(1536, FLOAT32),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_restaurant_vectors PRIMARY KEY (id),
CONSTRAINT fk_rv_restaurant FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)
);
CREATE VECTOR INDEX idx_rv_embedding
ON restaurant_vectors (embedding)
ORGANIZATION NEIGHBOR PARTITIONS
WITH DISTANCE COSINE;
-- Useful indexes
CREATE INDEX idx_videos_status ON videos(status);
CREATE INDEX idx_videos_channel ON videos(channel_id);
CREATE INDEX idx_vr_restaurant ON video_restaurants(restaurant_id);
CREATE INDEX idx_ur_restaurant ON user_reviews(restaurant_id);
CREATE INDEX idx_ur_user ON user_reviews(user_id);