db: create initial schema migration with pgvector
This commit is contained in:
parent
608bf086ec
commit
18734726cb
1 changed files with 85 additions and 0 deletions
85
supabase/migrations/00001_initial_schema.sql
Normal file
85
supabase/migrations/00001_initial_schema.sql
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
-- Enable the pgvector extension to work with embeddings
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- Users Table (Recruiters / Managers)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
role TEXT NOT NULL CHECK (role IN ('recruiter', 'manager')),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Jobs Table
|
||||
CREATE TABLE IF NOT EXISTS jobs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
requirements TEXT,
|
||||
embedding vector(1536),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Candidates Table
|
||||
CREATE TABLE IF NOT EXISTS candidates (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
phone TEXT,
|
||||
resume_url TEXT,
|
||||
summary TEXT,
|
||||
seniority TEXT,
|
||||
embedding vector(1536),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Interviews Table
|
||||
CREATE TABLE IF NOT EXISTS interviews (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
candidate_id UUID REFERENCES candidates(id) ON DELETE CASCADE NOT NULL,
|
||||
job_id UUID REFERENCES jobs(id) ON DELETE CASCADE NOT NULL,
|
||||
scheduled_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('scheduled', 'completed', 'cancelled')) DEFAULT 'scheduled',
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Scores Table
|
||||
CREATE TABLE IF NOT EXISTS scores (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
candidate_id UUID REFERENCES candidates(id) ON DELETE CASCADE NOT NULL,
|
||||
job_id UUID REFERENCES jobs(id) ON DELETE CASCADE NOT NULL,
|
||||
interviewer_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
score NUMERIC NOT NULL CHECK (score >= 0 AND score <= 100),
|
||||
evaluation JSONB, -- MUST contain exactly: summary, classification, suggestions, riskLevel
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- RPC Function to Match Candidates using Cosine Distance
|
||||
CREATE OR REPLACE FUNCTION match_candidates (
|
||||
query_embedding vector(1536),
|
||||
match_threshold FLOAT,
|
||||
match_count INT
|
||||
)
|
||||
RETURNS TABLE (
|
||||
id UUID,
|
||||
name TEXT,
|
||||
email TEXT,
|
||||
seniority TEXT,
|
||||
similarity FLOAT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT
|
||||
candidates.id,
|
||||
candidates.name,
|
||||
candidates.email,
|
||||
candidates.seniority,
|
||||
(1 - (candidates.embedding <=> query_embedding))::FLOAT AS similarity
|
||||
FROM candidates
|
||||
WHERE (1 - (candidates.embedding <=> query_embedding)) > match_threshold
|
||||
ORDER BY candidates.embedding <=> query_embedding ASC
|
||||
LIMIT match_count;
|
||||
END;
|
||||
$$;
|
||||
Loading…
Reference in a new issue