jobsonar / db /schema.sql
MiniMing
feat: employment_type filter + remove emojis + pill-style checklist UI
5ffbc31
-- JobSonar Database Schema
-- SQLite (๋กœ์ปฌ ๊ฐœ๋ฐœ) / PostgreSQL (ํ”„๋กœ๋•์…˜) ํ˜ธํ™˜
-- ์ฑ„์šฉ๊ณต๊ณ  ๋ฉ”์ธ ํ…Œ์ด๋ธ”
CREATE TABLE IF NOT EXISTS jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_site TEXT NOT NULL, -- 'wanted' | 'saramin' | 'jobkorea'
source_id TEXT NOT NULL, -- ์‚ฌ์ดํŠธ๋ณ„ ๊ณ ์œ  ID (์ค‘๋ณต ๋ฐฉ์ง€)
url TEXT NOT NULL,
title TEXT NOT NULL, -- ๊ณต๊ณ  ์ œ๋ชฉ
company_name TEXT NOT NULL,
job_category TEXT, -- '๋ฐ์ดํ„ฐ ์—”์ง€๋‹ˆ์–ด' | '๋ฐ์ดํ„ฐ ๋ถ„์„๊ฐ€' ๋“ฑ
industry TEXT, -- ํšŒ์‚ฌ ์—…์ข… (์›ํ‹ฐ๋“œ: API, ์‚ฌ๋žŒ์ธ/์žก์ฝ”๋ฆฌ์•„: HTML)
employment_type TEXT, -- '์ •๊ทœ์ง' | '๊ณ„์•ฝ์ง' | '์ธํ„ด' ๋“ฑ
location TEXT, -- '์„œ์šธ' | 'ํŒ๊ต' ๋“ฑ
experience_min INTEGER, -- ์ตœ์†Œ ๊ฒฝ๋ ฅ (๋…„)
experience_max INTEGER, -- ์ตœ๋Œ€ ๊ฒฝ๋ ฅ (๋…„), NULL = ๋ฌด๊ด€
salary_min INTEGER, -- ์—ฐ๋ด‰ ํ•˜ํ•œ (๋งŒ์›)
salary_max INTEGER, -- ์—ฐ๋ด‰ ์ƒํ•œ (๋งŒ์›)
posted_date DATE, -- ๊ณต๊ณ  ๊ฒŒ์‹œ์ผ
deadline_date DATE, -- ๋งˆ๊ฐ์ผ
is_active BOOLEAN NOT NULL DEFAULT 1,
is_duplicate BOOLEAN NOT NULL DEFAULT 0, -- ํƒ€ ์‚ฌ์ดํŠธ ๋™์ผ ๊ณต๊ณ  ์ค‘๋ณต ์—ฌ๋ถ€
collected_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(source_site, source_id)
);
-- ๊ธฐ์ˆ  ์Šคํƒ ํ…Œ์ด๋ธ” (๊ณต๊ณ ๋ณ„ ํƒœ๊ทธ)
CREATE TABLE IF NOT EXISTS job_skills (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
skill_name TEXT NOT NULL, -- ์ •๊ทœํ™”๋œ ์Šคํ‚ฌ๋ช… (์†Œ๋ฌธ์ž)
UNIQUE(job_id, skill_name)
);
-- ์ˆ˜์ง‘ ์‹คํ–‰ ๋กœ๊ทธ (GitHub Actions ๋””๋ฒ„๊น…์šฉ)
CREATE TABLE IF NOT EXISTS crawl_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_site TEXT NOT NULL,
started_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
finished_at DATETIME,
jobs_found INTEGER DEFAULT 0,
jobs_inserted INTEGER DEFAULT 0,
jobs_updated INTEGER DEFAULT 0,
status TEXT NOT NULL DEFAULT 'running', -- 'running' | 'success' | 'failed'
error_message TEXT
);
-- ์ธ๋ฑ์Šค
CREATE INDEX IF NOT EXISTS idx_jobs_source ON jobs(source_site, source_id);
CREATE INDEX IF NOT EXISTS idx_jobs_dedup ON jobs(lower(company_name), lower(title));
CREATE INDEX IF NOT EXISTS idx_jobs_category ON jobs(job_category);
CREATE INDEX IF NOT EXISTS idx_jobs_posted ON jobs(posted_date);
CREATE INDEX IF NOT EXISTS idx_jobs_active ON jobs(is_active);
CREATE INDEX IF NOT EXISTS idx_job_skills_name ON job_skills(skill_name);
CREATE INDEX IF NOT EXISTS idx_job_skills_job ON job_skills(job_id);