Lesson 18 / 25
pgvector for Embeddings
Similarity search inside Postgres.
Vectors next to your data
The pgvector extension adds a vector column type and distance operators: <-> (Euclidean), <#> (negative inner product) and <=> (cosine distance). Store an embedding per document produced by an embedding model, add an HNSW index for fast approximate search, and wrap the nearest-neighbour query in a function you call with rpc(). Because it is plain SQL, you can combine similarity with normal filters and RLS.
A documents table and a match function
SQL; dimensions must match your model.
create extension if not exists vector with schema extensions;
create table public.documents (
id bigint generated always as identity primary key,
content text not null,
embedding extensions.vector(1536)
);
create index on public.documents
using hnsw (embedding extensions.vector_cosine_ops);
create or replace function public.match_documents(query_embedding extensions.vector(1536), match_count int)
returns table (id bigint, content text, similarity float)
language sql stable
set search_path = public, extensions
as $$
select d.id, d.content, 1 - (d.embedding <=> query_embedding) as similarity
from public.documents d
order by d.embedding <=> query_embedding
limit match_count;
$$;
-- client: supabase.rpc('match_documents', { query_embedding: vec, match_count: 5 })Match dimensions and distance to the model
The vector size must equal the embedding model's output, and the index operator class should match the distance you query with.
Quick check: Which pgvector operator gives cosine distance?
- <=>
- <->
- <#>
- @>
Answer
<=> — <-> is Euclidean, <#> is negative inner product.