Vector Search Examples and Use Cases
Vector Search Examples and Use Cases
Version: v7.0 Status: Production Ready
Overview
This document provides production-ready examples for common vector search use cases including semantic search, image similarity, recommendation systems, RAG pipelines, and hybrid search.
1. Semantic Search
Find documents based on meaning rather than exact keyword matches.
Schema Setup
-- Create documents tableCREATE TABLE articles ( id SERIAL PRIMARY KEY, title VARCHAR(500), content TEXT, author VARCHAR(100), published_date DATE, category VARCHAR(50), embedding VECTOR(768) -- BERT-base dimension);
-- Create HNSW index for semantic searchCREATE INDEX idx_articles_semantic ON articles USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200);
-- Create supporting indexesCREATE INDEX idx_articles_category ON articles(category);CREATE INDEX idx_articles_date ON articles(published_date);Insert Documents with Embeddings
-- Insert article with pre-computed embeddingINSERT INTO articles (title, content, author, published_date, category, embedding)VALUES ( 'Introduction to Machine Learning', 'Machine learning is a subset of artificial intelligence that enables systems to learn and improve from experience without being explicitly programmed...', 'Dr. Jane Smith', '2024-01-15', 'Technology', '[0.023, -0.041, 0.087, ...]'::VECTOR -- 768 dimensions);
-- Batch insert from staging tableINSERT INTO articles (title, content, author, published_date, category, embedding)SELECT title, content, author, published_date, category, generate_embedding(content, 'bert-base') -- Built-in embedding functionFROM staging_articles;Semantic Search Queries
-- Basic semantic searchSELECT id, title, LEFT(content, 200) AS snippet, embedding <=> query_embedding AS relevanceFROM articlesORDER BY embedding <=> '[0.025, -0.041, ...]'::VECTORLIMIT 10;
-- Semantic search with category filterSELECT id, title, relevanceFROM ( SELECT id, title, embedding <=> query_embedding AS relevance FROM articles WHERE category = 'Technology') subWHERE relevance < 0.5 -- Similarity thresholdORDER BY relevanceLIMIT 10;
-- Semantic search with date rangeSELECT id, title, published_date, embedding <=> query_embedding AS relevanceFROM articlesWHERE published_date BETWEEN '2024-01-01' AND '2024-12-31'ORDER BY embedding <=> query_embeddingLIMIT 20;2. Image Similarity Search
Find visually similar images using CNN embeddings.
Schema Setup
-- Create images tableCREATE TABLE images ( id SERIAL PRIMARY KEY, filename VARCHAR(255), file_path TEXT, file_size BIGINT, width INT, height INT, format VARCHAR(10), tags TEXT[], uploaded_at TIMESTAMP DEFAULT NOW(), embedding VECTOR(2048) -- ResNet-50 dimension);
-- Create L2 index (better for image embeddings)CREATE INDEX idx_images_visual ON images USING hnsw (embedding vector_l2_ops) WITH (m = 24, ef_construction = 300);
-- Create GIN index for tag searchCREATE INDEX idx_images_tags ON images USING gin(tags);Insert Images
-- Insert image with embeddingINSERT INTO images (filename, file_path, width, height, format, tags, embedding)VALUES ( 'sunset_beach.jpg', '/uploads/2024/01/sunset_beach.jpg', 1920, 1080, 'jpeg', ARRAY['sunset', 'beach', 'nature', 'orange'], '[0.234, 0.567, -0.123, ...]'::VECTOR -- ResNet-50 embedding);Image Similarity Queries
-- Find similar images to a reference imageSELECT i2.id, i2.filename, i2.tags, i1.embedding <-> i2.embedding AS visual_distanceFROM images i1JOIN images i2 ON i1.id != i2.idWHERE i1.id = 12345 -- Reference image IDORDER BY i1.embedding <-> i2.embeddingLIMIT 20;
-- Find similar images by uploading query imageSELECT id, filename, file_path, embedding <-> query_embedding AS distanceFROM imagesORDER BY embedding <-> '[0.234, 0.567, ...]'::VECTORLIMIT 12;
-- Reverse image search with tag filterSELECT id, filename, tags, embedding <-> query_embedding AS distanceFROM imagesWHERE 'nature' = ANY(tags) -- Must have 'nature' tagORDER BY embedding <-> query_embeddingLIMIT 10;
-- Find images similar to multiple references (multi-query)WITH reference_images AS ( SELECT embedding FROM images WHERE id IN (100, 200, 300) -- Multiple reference images)SELECT DISTINCT ON (i.id) i.id, i.filename, MIN(r.embedding <-> i.embedding) AS min_distanceFROM images iCROSS JOIN reference_images rWHERE i.id NOT IN (100, 200, 300)GROUP BY i.id, i.filenameORDER BY i.id, min_distanceLIMIT 20;3. Recommendation System
Build a product recommendation engine using collaborative filtering embeddings.
Schema Setup
-- Products tableCREATE TABLE products ( id SERIAL PRIMARY KEY, name VARCHAR(500), description TEXT, category VARCHAR(100), price DECIMAL(10, 2), rating DECIMAL(3, 2), review_count INT, in_stock BOOLEAN DEFAULT true, embedding VECTOR(384) -- Product embedding);
-- User preferences tableCREATE TABLE user_preferences ( user_id INT PRIMARY KEY, preference_embedding VECTOR(384), -- Aggregated user taste last_updated TIMESTAMP DEFAULT NOW());
-- Purchase history for collaborative filteringCREATE TABLE purchases ( id SERIAL PRIMARY KEY, user_id INT, product_id INT, purchased_at TIMESTAMP DEFAULT NOW());
-- IndexesCREATE INDEX idx_products_rec ON products USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200);
CREATE INDEX idx_user_prefs ON user_preferences USING hnsw (preference_embedding vector_cosine_ops);Recommendation Queries
-- Content-based: Similar products to one the user likedSELECT p.id, p.name, p.price, p.rating, ref.embedding <=> p.embedding AS similarityFROM products refJOIN products p ON ref.id != p.idWHERE ref.id = 12345 -- Product user liked AND p.in_stock = true AND p.category = ref.categoryORDER BY ref.embedding <=> p.embeddingLIMIT 10;
-- Collaborative filtering: Products for user based on taste profileSELECT p.id, p.name, p.price, p.rating, u.preference_embedding <=> p.embedding AS match_scoreFROM user_preferences uJOIN products p ON p.in_stock = trueWHERE u.user_id = 98765ORDER BY u.preference_embedding <=> p.embeddingLIMIT 20;
-- Hybrid recommendation: Similar products + popularity boostSELECT p.id, p.name, p.price, p.rating, (0.7 * (1 - (ref.embedding <=> p.embedding)) + 0.2 * (p.rating / 5.0) + 0.1 * LEAST(p.review_count / 1000.0, 1.0)) AS hybrid_scoreFROM products refJOIN products p ON ref.id != p.idWHERE ref.id = 12345 AND p.in_stock = trueORDER BY hybrid_score DESCLIMIT 10;
-- "Customers who bought this also bought" (collaborative)WITH buyers AS ( SELECT DISTINCT user_id FROM purchases WHERE product_id = 12345),co_purchases AS ( SELECT product_id, COUNT(*) AS purchase_count FROM purchases WHERE user_id IN (SELECT user_id FROM buyers) AND product_id != 12345 GROUP BY product_id)SELECT p.id, p.name, p.price, cp.purchase_count, ref.embedding <=> p.embedding AS similarityFROM co_purchases cpJOIN products p ON cp.product_id = p.idJOIN products ref ON ref.id = 12345WHERE p.in_stock = trueORDER BY (0.6 * (1 - (ref.embedding <=> p.embedding)) + 0.4 * (cp.purchase_count::float / (SELECT MAX(purchase_count) FROM co_purchases))) DESCLIMIT 10;4. RAG Pipeline (Retrieval-Augmented Generation)
Build a knowledge base for LLM-powered question answering.
Schema Setup
-- Knowledge base chunksCREATE TABLE knowledge_chunks ( id SERIAL PRIMARY KEY, document_id INT, chunk_index INT, content TEXT, token_count INT, source_file VARCHAR(500), page_number INT, created_at TIMESTAMP DEFAULT NOW(), embedding VECTOR(1536) -- OpenAI text-embedding-ada-002);
-- Source documentsCREATE TABLE source_documents ( id SERIAL PRIMARY KEY, title VARCHAR(500), file_path TEXT, doc_type VARCHAR(50), -- pdf, docx, md, html upload_date DATE, metadata JSONB);
-- High-accuracy index for RAGCREATE INDEX idx_knowledge_rag ON knowledge_chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 32, ef_construction = 400);
-- Full-text search index for hybrid RAGCREATE INDEX idx_knowledge_fts ON knowledge_chunks USING gin(to_tsvector('english', content));RAG Retrieval Queries
-- Basic RAG retrievalSELECT kc.id, kc.content, sd.title AS source_title, kc.page_number, kc.embedding <=> query_embedding AS relevanceFROM knowledge_chunks kcJOIN source_documents sd ON kc.document_id = sd.idORDER BY kc.embedding <=> '[0.023, -0.041, ...]'::VECTORLIMIT 5;
-- Hybrid RAG: Vector + keyword searchWITH vector_results AS ( SELECT id, content, document_id, embedding <=> query_embedding AS vector_score FROM knowledge_chunks ORDER BY embedding <=> query_embedding LIMIT 20),keyword_results AS ( SELECT id, content, document_id, ts_rank(to_tsvector('english', content), plainto_tsquery('english', 'machine learning')) AS keyword_score FROM knowledge_chunks WHERE to_tsvector('english', content) @@ plainto_tsquery('english', 'machine learning') LIMIT 20)SELECT COALESCE(v.id, k.id) AS id, COALESCE(v.content, k.content) AS content, COALESCE(v.document_id, k.document_id) AS document_id, (0.7 * (1 - COALESCE(v.vector_score, 1)) + 0.3 * COALESCE(k.keyword_score, 0)) AS hybrid_scoreFROM vector_results vFULL OUTER JOIN keyword_results k ON v.id = k.idORDER BY hybrid_score DESCLIMIT 5;
-- Context window management (stay within token budget)WITH ranked_chunks AS ( SELECT id, content, token_count, embedding <=> query_embedding AS relevance, SUM(token_count) OVER (ORDER BY embedding <=> query_embedding) AS cumulative_tokens FROM knowledge_chunks ORDER BY embedding <=> query_embedding)SELECT id, content, relevanceFROM ranked_chunksWHERE cumulative_tokens <= 3000 -- Max context tokensORDER BY relevance;
-- Multi-source RAG with source attributionSELECT kc.content, sd.title AS source, sd.doc_type, kc.page_number, kc.embedding <=> query_embedding AS relevanceFROM knowledge_chunks kcJOIN source_documents sd ON kc.document_id = sd.idWHERE sd.doc_type IN ('pdf', 'docx') -- Only official documentsORDER BY kc.embedding <=> query_embeddingLIMIT 5;Building RAG Context
-- Create function to build RAG contextCREATE OR REPLACE FUNCTION build_rag_context( query_text TEXT, max_tokens INT DEFAULT 3000)RETURNS TABLE (context TEXT, sources TEXT[]) AS $$DECLARE query_embedding VECTOR(1536);BEGIN -- Generate query embedding (pseudo-code) query_embedding := generate_embedding(query_text, 'text-embedding-ada-002');
RETURN QUERY WITH chunks AS ( SELECT kc.content, sd.title, kc.token_count, SUM(kc.token_count) OVER (ORDER BY kc.embedding <=> query_embedding) AS cum_tokens FROM knowledge_chunks kc JOIN source_documents sd ON kc.document_id = sd.id ORDER BY kc.embedding <=> query_embedding ) SELECT string_agg(content, E'\n\n---\n\n') AS context, array_agg(DISTINCT title) AS sources FROM chunks WHERE cum_tokens <= max_tokens;END;$$ LANGUAGE plpgsql;
-- UsageSELECT * FROM build_rag_context('What are the best practices for vector indexing?');5. Hybrid Search (Vector + Text)
Combine semantic similarity with traditional full-text search for best results.
Schema Setup
-- Documents with both vector and text indexesCREATE TABLE searchable_docs ( id SERIAL PRIMARY KEY, title VARCHAR(500), content TEXT, category VARCHAR(100), created_at TIMESTAMP DEFAULT NOW(), embedding VECTOR(768));
-- Vector indexCREATE INDEX idx_docs_vector ON searchable_docs USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200);
-- Full-text search indexCREATE INDEX idx_docs_fts ON searchable_docs USING gin(to_tsvector('english', title || ' ' || content));Hybrid Search Queries
-- Reciprocal Rank Fusion (RRF) hybrid searchWITH vector_ranked AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> query_embedding) AS rank FROM searchable_docs ORDER BY embedding <=> query_embedding LIMIT 100),keyword_ranked AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank(to_tsvector('english', content), query) DESC) AS rank FROM searchable_docs WHERE to_tsvector('english', content) @@ plainto_tsquery('english', 'machine learning') LIMIT 100)SELECT d.id, d.title, LEFT(d.content, 200) AS snippet, (1.0 / (60 + COALESCE(v.rank, 1000)) + 1.0 / (60 + COALESCE(k.rank, 1000))) AS rrf_scoreFROM searchable_docs dLEFT JOIN vector_ranked v ON d.id = v.idLEFT JOIN keyword_ranked k ON d.id = k.idWHERE v.id IS NOT NULL OR k.id IS NOT NULLORDER BY rrf_score DESCLIMIT 10;
-- Weighted hybrid searchSELECT d.id, d.title, (0.7 * (1 - (d.embedding <=> query_embedding)) + 0.3 * COALESCE(ts_rank(to_tsvector('english', d.content), plainto_tsquery('english', 'neural networks')), 0)) AS hybrid_scoreFROM searchable_docs dWHERE d.embedding <=> query_embedding < 0.8 OR to_tsvector('english', d.content) @@ plainto_tsquery('english', 'neural networks')ORDER BY hybrid_score DESCLIMIT 10;
-- Adaptive hybrid search (adjust weights based on query type)CREATE OR REPLACE FUNCTION adaptive_hybrid_search( query_text TEXT, query_embedding VECTOR(768), result_count INT DEFAULT 10)RETURNS TABLE (id INT, title VARCHAR, score FLOAT) AS $$DECLARE has_specific_terms BOOLEAN; vector_weight FLOAT; keyword_weight FLOAT;BEGIN -- Detect if query has specific/technical terms has_specific_terms := query_text ~* '\m(API|SDK|UUID|JSON|SQL)\M';
-- Adjust weights IF has_specific_terms THEN vector_weight := 0.3; keyword_weight := 0.7; ELSE vector_weight := 0.7; keyword_weight := 0.3; END IF;
RETURN QUERY SELECT d.id, d.title, (vector_weight * (1 - (d.embedding <=> query_embedding)) + keyword_weight * COALESCE(ts_rank(to_tsvector('english', d.content), plainto_tsquery('english', query_text)), 0))::FLOAT FROM searchable_docs d ORDER BY 3 DESC LIMIT result_count;END;$$ LANGUAGE plpgsql;6. Multi-Modal Search
Search across text and images using unified embeddings (CLIP).
Schema Setup
-- Multi-modal contentCREATE TABLE multi_modal_content ( id SERIAL PRIMARY KEY, content_type VARCHAR(20), -- 'text', 'image', 'video' title VARCHAR(500), description TEXT, file_path TEXT, thumbnail_path TEXT, metadata JSONB, created_at TIMESTAMP DEFAULT NOW(), clip_embedding VECTOR(512) -- CLIP embedding (unified space));
-- Unified index for cross-modal searchCREATE INDEX idx_multimodal_clip ON multi_modal_content USING hnsw (clip_embedding vector_cosine_ops) WITH (m = 24, ef_construction = 300);Cross-Modal Search Queries
-- Search images with text query-- Text "sunset on beach" embedding searches image embeddingsSELECT id, content_type, title, file_path, clip_embedding <=> text_query_embedding AS relevanceFROM multi_modal_contentWHERE content_type = 'image'ORDER BY clip_embedding <=> '[...]'::VECTOR -- CLIP text embeddingLIMIT 12;
-- Search all content types with image querySELECT id, content_type, title, description, clip_embedding <=> image_query_embedding AS relevanceFROM multi_modal_contentORDER BY clip_embedding <=> '[...]'::VECTOR -- CLIP image embeddingLIMIT 20;
-- Find text descriptions for similar imagesWITH image_results AS ( SELECT id, clip_embedding FROM multi_modal_content WHERE content_type = 'image' ORDER BY clip_embedding <=> query_embedding LIMIT 10)SELECT t.id, t.title, t.description, MIN(ir.clip_embedding <=> t.clip_embedding) AS similarityFROM image_results irCROSS JOIN multi_modal_content tWHERE t.content_type = 'text'GROUP BY t.id, t.title, t.descriptionORDER BY similarityLIMIT 5;7. Anomaly Detection
Detect outliers and anomalies using vector distance.
Schema Setup
-- System metrics tableCREATE TABLE system_metrics ( id SERIAL PRIMARY KEY, timestamp TIMESTAMP, server_id VARCHAR(50), cpu_usage FLOAT, memory_usage FLOAT, disk_io FLOAT, network_io FLOAT, request_count INT, error_count INT, feature_vector VECTOR(128) -- Normalized metric embedding);
-- Index for fast neighbor searchCREATE INDEX idx_metrics_anomaly ON system_metrics USING hnsw (feature_vector vector_l2_ops) WITH (m = 16, ef_construction = 200);Anomaly Detection Queries
-- Find outliers: points with no close neighborsWITH neighbor_distances AS ( SELECT m1.id, m1.timestamp, m1.server_id, MIN(m1.feature_vector <-> m2.feature_vector) AS nearest_distance FROM system_metrics m1 JOIN system_metrics m2 ON m1.id != m2.id AND m2.timestamp BETWEEN m1.timestamp - INTERVAL '1 hour' AND m1.timestamp + INTERVAL '1 hour' GROUP BY m1.id, m1.timestamp, m1.server_id)SELECT *FROM neighbor_distancesWHERE nearest_distance > ( SELECT PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY nearest_distance) FROM neighbor_distances)ORDER BY nearest_distance DESC;
-- Real-time anomaly detection for new data pointSELECT CASE WHEN MIN(new_point.feature_vector <-> m.feature_vector) > 2.5 THEN 'ANOMALY' ELSE 'NORMAL' END AS status, MIN(new_point.feature_vector <-> m.feature_vector) AS min_distanceFROM ( SELECT '[0.5, 0.3, ...]'::VECTOR AS feature_vector) new_pointCROSS JOIN system_metrics mWHERE m.timestamp > NOW() - INTERVAL '24 hours';
-- Cluster-based anomaly detectionWITH cluster_centers AS ( -- Use K-means or pre-defined cluster centers SELECT id, feature_vector FROM (VALUES (1, '[0.1, 0.2, ...]'::VECTOR), (2, '[0.5, 0.3, ...]'::VECTOR), (3, '[0.8, 0.1, ...]'::VECTOR) ) AS centers(id, feature_vector))SELECT m.id, m.timestamp, MIN(m.feature_vector <-> c.feature_vector) AS cluster_distance, CASE WHEN MIN(m.feature_vector <-> c.feature_vector) > 3.0 THEN 'ANOMALY' ELSE 'NORMAL' END AS statusFROM system_metrics mCROSS JOIN cluster_centers cGROUP BY m.id, m.timestampORDER BY cluster_distance DESCLIMIT 100;8. Code Search
Search code repositories by functionality description.
Schema Setup
-- Code functions tableCREATE TABLE code_functions ( id SERIAL PRIMARY KEY, repo_name VARCHAR(200), file_path TEXT, function_name VARCHAR(200), signature TEXT, docstring TEXT, body TEXT, language VARCHAR(50), complexity_score INT, embedding VECTOR(768) -- CodeBERT embedding);
-- Index for semantic code searchCREATE INDEX idx_code_semantic ON code_functions USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200);
-- Full-text index for identifier searchCREATE INDEX idx_code_fts ON code_functions USING gin(to_tsvector('simple', function_name || ' ' || COALESCE(docstring, '')));Code Search Queries
-- Semantic code search: "function to parse JSON with error handling"SELECT repo_name, file_path, function_name, signature, LEFT(docstring, 200) AS docstring_preview, embedding <=> query_embedding AS relevanceFROM code_functionsWHERE language = 'python'ORDER BY embedding <=> '[...]'::VECTORLIMIT 10;
-- Find similar implementationsSELECT cf2.repo_name, cf2.file_path, cf2.function_name, cf2.signature, cf1.embedding <=> cf2.embedding AS similarityFROM code_functions cf1JOIN code_functions cf2 ON cf1.id != cf2.idWHERE cf1.id = 12345 -- Reference function AND cf2.language = cf1.languageORDER BY cf1.embedding <=> cf2.embeddingLIMIT 10;
-- Hybrid: semantic + identifier searchSELECT function_name, file_path, (0.6 * (1 - (embedding <=> query_embedding)) + 0.4 * COALESCE(ts_rank(to_tsvector('simple', function_name || ' ' || COALESCE(docstring, '')), plainto_tsquery('simple', 'parse json')), 0)) AS scoreFROM code_functionsORDER BY score DESCLIMIT 10;Performance Tips for All Examples
1. Use Appropriate Index Settings
-- For high-throughput (web search)WITH (m = 16, ef_construction = 200) -- SET hnsw.ef_search = 40
-- For high accuracy (RAG, recommendations)WITH (m = 32, ef_construction = 400) -- SET hnsw.ef_search = 2002. Pre-filter When Possible
-- Good: Filter then searchSELECT * FROM productsWHERE category = 'Electronics' AND in_stock = trueORDER BY embedding <=> queryLIMIT 10;
-- Less efficient: Search then filterSELECT * FROM ( SELECT * FROM products ORDER BY embedding <=> query LIMIT 1000) subWHERE category = 'Electronics';3. Use Connection Pooling
-- Configure for concurrent vector queriesSET max_parallel_workers_per_gather = 4;SET work_mem = '256MB';4. Monitor Query Performance
-- Check query planEXPLAIN (ANALYZE, BUFFERS)SELECT * FROM documentsORDER BY embedding <=> query_vectorLIMIT 10;Status: Production Ready Version: v7.0 Last Updated: January 2026