---
title: "Vector Search Examples and Use Cases"
---

# Vector Search Examples and Use Cases


---

## Overview

This document provides 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

```sql
-- Create documents table
CREATE 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 search
CREATE INDEX idx_articles_semantic ON articles
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 200);

-- Create supporting indexes
CREATE INDEX idx_articles_category ON articles(category);
CREATE INDEX idx_articles_date ON articles(published_date);
```

### Insert Documents with Embeddings

```sql
-- Insert article with pre-computed embedding
INSERT 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 table
INSERT INTO articles (title, content, author, published_date, category, embedding)
SELECT
    title,
    content,
    author,
    published_date,
    category,
    generate_embedding(content, 'bert-base')  -- Built-in embedding function
FROM staging_articles;
```

### Semantic Search Queries

```sql
-- Basic semantic search
SELECT
    id,
    title,
    LEFT(content, 200) AS snippet,
    embedding <=> query_embedding AS relevance
FROM articles
ORDER BY embedding <=> '[0.025, -0.041, ...]'::VECTOR
LIMIT 10;

-- Semantic search with category filter
SELECT id, title, relevance
FROM (
    SELECT
        id,
        title,
        embedding <=> query_embedding AS relevance
    FROM articles
    WHERE category = 'Technology'
) sub
WHERE relevance < 0.5  -- Similarity threshold
ORDER BY relevance
LIMIT 10;

-- Semantic search with date range
SELECT
    id,
    title,
    published_date,
    embedding <=> query_embedding AS relevance
FROM articles
WHERE published_date BETWEEN '2024-01-01' AND '2024-12-31'
ORDER BY embedding <=> query_embedding
LIMIT 20;
```

---

## 2. Image Similarity Search

Find visually similar images using CNN embeddings.

### Schema Setup

```sql
-- Create images table
CREATE 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 search
CREATE INDEX idx_images_tags ON images USING gin(tags);
```

### Insert Images

```sql
-- Insert image with embedding
INSERT 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

```sql
-- Find similar images to a reference image
SELECT
    i2.id,
    i2.filename,
    i2.tags,
    i1.embedding <-> i2.embedding AS visual_distance
FROM images i1
JOIN images i2 ON i1.id != i2.id
WHERE i1.id = 12345  -- Reference image ID
ORDER BY i1.embedding <-> i2.embedding
LIMIT 20;

-- Find similar images by uploading query image
SELECT
    id,
    filename,
    file_path,
    embedding <-> query_embedding AS distance
FROM images
ORDER BY embedding <-> '[0.234, 0.567, ...]'::VECTOR
LIMIT 12;

-- Reverse image search with tag filter
SELECT
    id,
    filename,
    tags,
    embedding <-> query_embedding AS distance
FROM images
WHERE 'nature' = ANY(tags)  -- Must have 'nature' tag
ORDER BY embedding <-> query_embedding
LIMIT 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_distance
FROM images i
CROSS JOIN reference_images r
WHERE i.id NOT IN (100, 200, 300)
GROUP BY i.id, i.filename
ORDER BY i.id, min_distance
LIMIT 20;
```

---

## 3. Recommendation System

Build a product recommendation engine using collaborative filtering embeddings.

### Schema Setup

```sql
-- Products table
CREATE 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 table
CREATE TABLE user_preferences (
    user_id INT PRIMARY KEY,
    preference_embedding VECTOR(384),  -- Aggregated user taste
    last_updated TIMESTAMP DEFAULT NOW()
);

-- Purchase history for collaborative filtering
CREATE TABLE purchases (
    id SERIAL PRIMARY KEY,
    user_id INT,
    product_id INT,
    purchased_at TIMESTAMP DEFAULT NOW()
);

-- Indexes
CREATE 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

```sql
-- Content-based: Similar products to one the user liked
SELECT
    p.id,
    p.name,
    p.price,
    p.rating,
    ref.embedding <=> p.embedding AS similarity
FROM products ref
JOIN products p ON ref.id != p.id
WHERE ref.id = 12345  -- Product user liked
  AND p.in_stock = true
  AND p.category = ref.category
ORDER BY ref.embedding <=> p.embedding
LIMIT 10;

-- Collaborative filtering: Products for user based on taste profile
SELECT
    p.id,
    p.name,
    p.price,
    p.rating,
    u.preference_embedding <=> p.embedding AS match_score
FROM user_preferences u
JOIN products p ON p.in_stock = true
WHERE u.user_id = 98765
ORDER BY u.preference_embedding <=> p.embedding
LIMIT 20;

-- Hybrid recommendation: Similar products + popularity boost
SELECT
    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_score
FROM products ref
JOIN products p ON ref.id != p.id
WHERE ref.id = 12345
  AND p.in_stock = true
ORDER BY hybrid_score DESC
LIMIT 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 similarity
FROM co_purchases cp
JOIN products p ON cp.product_id = p.id
JOIN products ref ON ref.id = 12345
WHERE p.in_stock = true
ORDER BY (0.6 * (1 - (ref.embedding <=> p.embedding)) +
          0.4 * (cp.purchase_count::float / (SELECT MAX(purchase_count) FROM co_purchases))) DESC
LIMIT 10;
```

---

## 4. RAG Pipeline (Retrieval-Augmented Generation)

Build a knowledge base for LLM-powered question answering.

### Schema Setup

```sql
-- Knowledge base chunks
CREATE 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 documents
CREATE 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 RAG
CREATE 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 RAG
CREATE INDEX idx_knowledge_fts ON knowledge_chunks
  USING gin(to_tsvector('english', content));
```

### RAG Retrieval Queries

```sql
-- Basic RAG retrieval
SELECT
    kc.id,
    kc.content,
    sd.title AS source_title,
    kc.page_number,
    kc.embedding <=> query_embedding AS relevance
FROM knowledge_chunks kc
JOIN source_documents sd ON kc.document_id = sd.id
ORDER BY kc.embedding <=> '[0.023, -0.041, ...]'::VECTOR
LIMIT 5;

-- Hybrid RAG: Vector + keyword search
WITH 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_score
FROM vector_results v
FULL OUTER JOIN keyword_results k ON v.id = k.id
ORDER BY hybrid_score DESC
LIMIT 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, relevance
FROM ranked_chunks
WHERE cumulative_tokens <= 3000  -- Max context tokens
ORDER BY relevance;

-- Multi-source RAG with source attribution
SELECT
    kc.content,
    sd.title AS source,
    sd.doc_type,
    kc.page_number,
    kc.embedding <=> query_embedding AS relevance
FROM knowledge_chunks kc
JOIN source_documents sd ON kc.document_id = sd.id
WHERE sd.doc_type IN ('pdf', 'docx')  -- Only official documents
ORDER BY kc.embedding <=> query_embedding
LIMIT 5;
```

### Building RAG Context

```sql
-- Create function to build RAG context
CREATE 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;

-- Usage
SELECT * 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

```sql
-- Documents with both vector and text indexes
CREATE TABLE searchable_docs (
    id SERIAL PRIMARY KEY,
    title VARCHAR(500),
    content TEXT,
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW(),
    embedding VECTOR(768)
);

-- Vector index
CREATE INDEX idx_docs_vector ON searchable_docs
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 200);

-- Full-text search index
CREATE INDEX idx_docs_fts ON searchable_docs
  USING gin(to_tsvector('english', title || ' ' || content));
```

### Hybrid Search Queries

```sql
-- Reciprocal Rank Fusion (RRF) hybrid search
WITH 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_score
FROM searchable_docs d
LEFT JOIN vector_ranked v ON d.id = v.id
LEFT JOIN keyword_ranked k ON d.id = k.id
WHERE v.id IS NOT NULL OR k.id IS NOT NULL
ORDER BY rrf_score DESC
LIMIT 10;

-- Weighted hybrid search
SELECT
    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_score
FROM searchable_docs d
WHERE d.embedding <=> query_embedding < 0.8
   OR to_tsvector('english', d.content) @@ plainto_tsquery('english', 'neural networks')
ORDER BY hybrid_score DESC
LIMIT 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

```sql
-- Multi-modal content
CREATE 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 search
CREATE 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

```sql
-- Search images with text query
-- Text "sunset on beach" embedding searches image embeddings
SELECT
    id,
    content_type,
    title,
    file_path,
    clip_embedding <=> text_query_embedding AS relevance
FROM multi_modal_content
WHERE content_type = 'image'
ORDER BY clip_embedding <=> '[...]'::VECTOR  -- CLIP text embedding
LIMIT 12;

-- Search all content types with image query
SELECT
    id,
    content_type,
    title,
    description,
    clip_embedding <=> image_query_embedding AS relevance
FROM multi_modal_content
ORDER BY clip_embedding <=> '[...]'::VECTOR  -- CLIP image embedding
LIMIT 20;

-- Find text descriptions for similar images
WITH 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 similarity
FROM image_results ir
CROSS JOIN multi_modal_content t
WHERE t.content_type = 'text'
GROUP BY t.id, t.title, t.description
ORDER BY similarity
LIMIT 5;
```

---

## 7. Anomaly Detection

Detect outliers and anomalies using vector distance.

### Schema Setup

```sql
-- System metrics table
CREATE 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 search
CREATE INDEX idx_metrics_anomaly ON system_metrics
  USING hnsw (feature_vector vector_l2_ops)
  WITH (m = 16, ef_construction = 200);
```

### Anomaly Detection Queries

```sql
-- Find outliers: points with no close neighbors
WITH 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_distances
WHERE 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 point
SELECT
    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_distance
FROM (
    SELECT '[0.5, 0.3, ...]'::VECTOR AS feature_vector
) new_point
CROSS JOIN system_metrics m
WHERE m.timestamp > NOW() - INTERVAL '24 hours';

-- Cluster-based anomaly detection
WITH 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 status
FROM system_metrics m
CROSS JOIN cluster_centers c
GROUP BY m.id, m.timestamp
ORDER BY cluster_distance DESC
LIMIT 100;
```

---

## 8. Code Search

Search code repositories by functionality description.

### Schema Setup

```sql
-- Code functions table
CREATE 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 search
CREATE INDEX idx_code_semantic ON code_functions
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 200);

-- Full-text index for identifier search
CREATE INDEX idx_code_fts ON code_functions
  USING gin(to_tsvector('simple', function_name || ' ' || COALESCE(docstring, '')));
```

### Code Search Queries

```sql
-- 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 relevance
FROM code_functions
WHERE language = 'python'
ORDER BY embedding <=> '[...]'::VECTOR
LIMIT 10;

-- Find similar implementations
SELECT
    cf2.repo_name,
    cf2.file_path,
    cf2.function_name,
    cf2.signature,
    cf1.embedding <=> cf2.embedding AS similarity
FROM code_functions cf1
JOIN code_functions cf2 ON cf1.id != cf2.id
WHERE cf1.id = 12345  -- Reference function
  AND cf2.language = cf1.language
ORDER BY cf1.embedding <=> cf2.embedding
LIMIT 10;

-- Hybrid: semantic + identifier search
SELECT
    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 score
FROM code_functions
ORDER BY score DESC
LIMIT 10;
```

---

## Performance Tips for All Examples

### 1. Use Appropriate Index Settings

```sql
-- 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 = 200
```

### 2. Pre-filter When Possible

```sql
-- Good: Filter then search
SELECT * FROM products
WHERE category = 'Electronics' AND in_stock = true
ORDER BY embedding <=> query
LIMIT 10;

-- Less efficient: Search then filter
SELECT * FROM (
    SELECT * FROM products ORDER BY embedding <=> query LIMIT 1000
) sub
WHERE category = 'Electronics';
```

### 3. Use Connection Pooling

```sql
-- Configure for concurrent vector queries
SET max_parallel_workers_per_gather = 4;
SET work_mem = '256MB';
```

### 4. Monitor Query Performance

```sql
-- Check query plan
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM documents
ORDER BY embedding <=> query_vector
LIMIT 10;
```

---
