Vector Operations
PostgreSQL uses the pgvector extension to store and search vectors. For common reads and writes, see Vector Type Mapping. For queries, see KNN Ordering and Distance Filtering.
Vector Type Mapping
vector(3) stores a three-dimensional vector, not a PostgreSQL array. Enable the extension before creating the field:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE vector_item (
id BIGINT PRIMARY KEY,
embedding vector(3)
);
Use List<Float> with PgVectorTypeHandler for this field; see Vector Type Handlers. Pass three-dimensional vectors for writes and queries; no manual conversion to PGobject is needed.
Binary vectors use a BIT(n) field and a query parameter whose PGobject type is bit. Do not use the floating-point vector handler for this field:
PGobject target = new PGobject();
target.setType("bit");
target.setValue("11110000"); // For BIT(8)
Distance Range Filtering
L2, cosine, and inner-product filters are supported, as are Hamming and Jaccard distance filters for BIT(n). pgvector does not provide BM25 scoring.
pgvector's <=> returns cosine distance, equal to 1 - cosine similarity. To find records with similarity greater than 0.8, pass a distance threshold of 0.2, not 0.8:
List<VectorItem> rows = lambda.query(VectorItem.class)
.vectorByCosine(VectorItem::getEmbedding, target, 0.2)
.queryForList();
Here, target is the query vector. The condition is embedding <=> ? < 0.2. orderByCosine sorts distance ascending, placing higher similarity first.
Query by Inner Product
pgvector's <#> returns the negative inner product. orderByIP sorts this value ascending, placing larger actual inner products first.
To find records with an inner product greater than 0.8, pass -0.8:
List<VectorItem> rows = lambda.query(VectorItem.class)
.vectorByIP(VectorItem::getEmbedding, target, -0.8)
.queryForList();
The condition is embedding <#> ? < -0.8.
KNN Ordering
For BIT(n), use orderByHamming or orderByJaccard to sort by ascending distance. Floating-point vectors use the three methods below. orderByBM25 is not supported.
Match the index to the query's distance metric:
| Builder API ordering | pgvector operator | Index operator class |
|---|---|---|
orderByL2 | <-> | vector_l2_ops |
orderByCosine | <=> | vector_cosine_ops |
orderByIP | <#> | vector_ip_ops |
For example, the HNSW index matching a top-10 orderByCosine query is:
CREATE INDEX vector_item_cosine_idx
ON vector_item USING hnsw (embedding vector_cosine_ops);
An L2 index cannot replace a cosine index. Indexed nearest-neighbor queries need ascending distance ordering and a limit; use orderByCosine(...).initPage(10, 0) in the Builder API. A vectorByCosine distance filter alone is not an indexed nearest-neighbor query.
See pgvector documentation for distance definitions and index options.
Combined Queries
Scalar and vector predicates are combined in WHERE. eq(...).orderByCosine(...).initPage(k, 0) restricts the result set to matching scalar values. With an approximate index, filtering can leave fewer than k results; k is not a guarantee of k matches. See Combined Conditions.