Skip to main content

Vector Operations

Choose the Search Path​

Elasticsearch vector queries depend on the server version and field mapping. An API method name alone does not select the server's vector engine.

PathBehavior
ES 7 script_scoreScore matching documents with a script.
ES 8.4+ _search knnNative approximate search on an indexed dense_vector.
Elastic7DialectUses script_score and descending _score ordering, not native knn.
Elastic8DialectProduces top-level knn with fixed k=10 and num_candidates=100; initPage does not change these values.

Vector Type Mapping​

ES 7 uses dense_vector with dims, without the ES 8 index and similarity options below. Bind numeric Lists when writing. Expanded vector fields are also returned as numeric Lists, not JSON text.

In ES 7.17, a dense_vector field may be absent and reads as null, but explicitly inserting or updating it to null is rejected. To clear an existing vector, remove the field with a native command instead of assigning null in a builder update.

For the ES 8.4+ kNN example, create this index first:

PUT /product_index
{
"mappings": {"properties": {
"category": {"type": "keyword"},
"embedding": {"type": "dense_vector", "dims": 3, "index": true, "similarity": "cosine"}
}}
}

The similarity setting determines the index metric. Calling orderByL2 does not change a cosine index into an L2 index.

Restrict the Vector Candidates​

To search only electronics documents, place the filter inside knn.filter and bind the vector as a numeric List:

String command = """
POST /product_index/_search
{
"size": 10,
"knn": {
"field": "embedding",
"query_vector": ?,
"k": 10,
"num_candidates": 100,
"filter": {"term": {"category": ?}}
}
}
""";
List<Map<String, Object>> rows = jdbc.queryForList(
command, new Object[] { List.of(0.1f, 0.2f, 0.3f), "electronics" });
Note

Elastic8Dialect places Fluent scalar conditions in top-level query, not knn.filter. Elasticsearch combines query and knn as alternatives; eq(...).orderByL2(...) is therefore not a mandatory candidate filter. Use the command above for tenant or category restrictions.

KNN Ordering​

Vector ordering integrates L2, cosine, and inner product. Hamming, Jaccard, and BM25 are not integrated into these builder methods; full-text BM25 scoring is a separate feature.

The ES 7 builder generates script_score and orders by _score descending. It supports one vector score per query, not native approximate kNN.

On ES 7, declare embedding as dense_vector with dims=3; omit the ES 8 index and similarity options. For cosine scoring, submit script_score:

String command = """
POST /product_index/_search
{
"size": 10,
"query": {"script_score": {
"query": {"term": {"category": ?}},
"script": {
"source": "cosineSimilarity(params.vec, 'embedding') + 1.0",
"params": {"vec": ?}
}
}}
}
""";
List<Map<String, Object>> rows = jdbc.queryForList(
command, new Object[] { "electronics", List.of(0.1f, 0.2f, 0.3f) });

Every matching document must contain embedding. The script adds 1 to keep scores nonnegative; the score is not the original cosine similarity.

Distance Range Filtering​

The ES 7 builder compares distances in a script and uses min_score=1 to retain matching documents. vectorByL2 compares L2 distance, vectorByCosine compares 1 - cosineSimilarity, and vectorByIP compares the negative inner product. All use < threshold.

Cosine similarity above 0.8 therefore uses 0.2; inner product above 0.8 uses -0.8. The range threshold is not the _score returned by vector ordering.

Hamming, Jaccard, and BM25 range filters are not available through the builder API.

Combined Queries​

The ES 7 builder puts scalar predicates in script_score.query, scoring only matching documents. eq(...).orderByCosine(...) restricts the candidate set; range filters can also combine scalar predicates. For ES 8, use the candidate-filtering command above rather than assuming ES 7 behavior.

Read Vector Values​

Read _DOC for the whole document. Read embedding as a numeric List; use Number.floatValue() when Float elements are needed:

List<?> values = (List<?>) row.get("embedding");
List<Float> embedding = values.stream()
.map(value -> ((Number) value).floatValue())
.toList();

Request syntax and version requirements: script_score、 kNN.