Skip to content

Commit 79893b5

Browse files
authored
Merge branch 'main' into esql-commands
2 parents 0b8c88d + b46e0ce commit 79893b5

File tree

110 files changed

+1281
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+1281
-438
lines changed

benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public void setup() {
9292
var fields = 10_000;
9393
var mapping = LinkedHashMap.<String, EsField>newLinkedHashMap(fields);
9494
for (int i = 0; i < fields; i++) {
95-
mapping.put("field" + i, new EsField("field-" + i, TEXT, emptyMap(), true));
95+
// We're creating a standard index, so none of these fields should be marked as dimensions.
96+
mapping.put("field" + i, new EsField("field-" + i, TEXT, emptyMap(), true, EsField.TimeSeriesFieldType.NONE));
9697
}
9798

9899
var esIndex = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD));

benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ private static EvalOperator.ExpressionEvaluator evaluator(String operation) {
212212
FieldAttribute timestamp = new FieldAttribute(
213213
Source.EMPTY,
214214
"timestamp",
215-
new EsField("timestamp", DataType.DATETIME, Map.of(), true)
215+
new EsField("timestamp", DataType.DATETIME, Map.of(), true, EsField.TimeSeriesFieldType.NONE)
216216
);
217217
yield EvalMapper.toEvaluator(
218218
FOLD_CONTEXT,
@@ -321,19 +321,35 @@ private static EvalOperator.ExpressionEvaluator evaluator(String operation) {
321321
}
322322

323323
private static FieldAttribute longField() {
324-
return new FieldAttribute(Source.EMPTY, "long", new EsField("long", DataType.LONG, Map.of(), true));
324+
return new FieldAttribute(
325+
Source.EMPTY,
326+
"long",
327+
new EsField("long", DataType.LONG, Map.of(), true, EsField.TimeSeriesFieldType.NONE)
328+
);
325329
}
326330

327331
private static FieldAttribute doubleField() {
328-
return new FieldAttribute(Source.EMPTY, "double", new EsField("double", DataType.DOUBLE, Map.of(), true));
332+
return new FieldAttribute(
333+
Source.EMPTY,
334+
"double",
335+
new EsField("double", DataType.DOUBLE, Map.of(), true, EsField.TimeSeriesFieldType.NONE)
336+
);
329337
}
330338

331339
private static FieldAttribute intField() {
332-
return new FieldAttribute(Source.EMPTY, "int", new EsField("int", DataType.INTEGER, Map.of(), true));
340+
return new FieldAttribute(
341+
Source.EMPTY,
342+
"int",
343+
new EsField("int", DataType.INTEGER, Map.of(), true, EsField.TimeSeriesFieldType.NONE)
344+
);
333345
}
334346

335347
private static FieldAttribute keywordField() {
336-
return new FieldAttribute(Source.EMPTY, "keyword", new EsField("keyword", DataType.KEYWORD, Map.of(), true));
348+
return new FieldAttribute(
349+
Source.EMPTY,
350+
"keyword",
351+
new EsField("keyword", DataType.KEYWORD, Map.of(), true, EsField.TimeSeriesFieldType.NONE)
352+
);
337353
}
338354

339355
private static Configuration configuration() {

docs/changelog/131907.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
pr: 131907
2+
summary: Enable `exclude_source_vectors` by default for new indices
3+
area: Vector Search
4+
type: breaking
5+
issues: []
6+
breaking:
7+
title: Enable `exclude_source_vectors` by default for new indices
8+
area: Search
9+
details: |-
10+
The `exclude_source_vectors` setting is now enabled by default for newly created indices.
11+
This means that vector fields (e.g., `dense_vector`) are no longer stored in the `_source` field
12+
by default, although they remain fully accessible through search and retrieval operations.
13+
14+
Instead of being persisted in `_source`, vectors are now rehydrated on demand from the underlying
15+
index structures when needed. This reduces index size and improves performance for typical vector
16+
search workloads where the original vector values do not need to be part of the `_source`.
17+
18+
If your use case requires vector fields to be stored in `_source`, you can disable this behavior by
19+
setting `exclude_source_vectors: false` at index creation time.
20+
impact: |-
21+
Vector fields will no longer be stored in `_source` by default for new indices. Applications or tools
22+
that expect to see vector fields in `_source` (for raw document inspection)
23+
may need to be updated or configured to explicitly retain vectors using `exclude_source_vectors: false`.
24+
25+
Retrieval of vector fields via search or the `_source` API remains fully supported.
26+
notable: true

docs/changelog/132766.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pr: 132766
2+
summary: Change `reporting_user` role to leverage reserved kibana privileges
3+
area: Authorization
4+
type: deprecation
5+
issues: []
6+
deprecation:
7+
title: Deprecate the built-in `reporting_user` role.
8+
area: Authorization
9+
details: The `reporting_user` role is deprecated. Administrators should manage access to Kibana's reporting features via custom roles which grant the necessary privileges.
10+
impact: This role will be removed in a future version. Administrators should migrate to custom roles to avoid interruption.

docs/changelog/132858.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 132858
2+
summary: Add index mode to resolve index response
3+
area: Indices APIs
4+
type: feature
5+
issues: []

docs/changelog/132945.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 132945
2+
summary: Disable child span for streaming tasks
3+
area: Machine Learning
4+
type: bug
5+
issues: []
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
---
2+
navigation_title: Better Binary Quantization (BBQ)
3+
applies_to:
4+
stack: all
5+
serverless: all
6+
---
7+
8+
# Better Binary Quantization (BBQ) [bbq]
9+
10+
Better Binary Quantization (BBQ) is an advanced vector quantization method, designed for large-scale similarity search. BBQ is a form of lossy compression for [`dense_vector` fields](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector) that enables efficient storage and retrieval of large numbers of vectors, while keeping results close to those from the original uncompressed vectors.
11+
12+
BBQ offers significant improvements over scalar quantization by relying on optimized `bit` level computations to reduce memory usage and computational costs while maintaining high search relevance using pre-computed corrective factors. BBQ is designed to work in combination with [oversampling](#bbq-oversampling) and reranking, and is compatible with various [vector search algorithms](#bbq-vector-search-algorithms), such as [HNSW](#bbq-hnsw) and [brute force (flat)](#bbq-flat).
13+
14+
## How BBQ works [bbq-how-it-works]
15+
16+
BBQ retains the original vector’s dimensionality but transforms the datatype of the dimensions from the original `float32` to `bit` effectively compressing each vector by 32x plus an additional 14 bytes of corrective data per vector. BBQ uses these pre-computed corrective factors as partial distance calculations to help realize impressively robust approximations of the original vector.
17+
18+
Measuring vector similarity with BBQ vectors requires much less computing effort, allowing more candidates to be considered when using the HNSW algorithm. This often results in better ranking quality and improved relevance compared to the original `float32` vectors.
19+
20+
## Supported vector search algorithms [bbq-vector-search-algorithms]
21+
22+
BBQ currently supports two vector search algorithms, each suited to different scenarios. You can configure them by setting the dense vector field’s `index_type`.
23+
24+
### `bbq_hnsw` [bbq-hnsw]
25+
26+
When you set a dense vector field’s `index_options` parameter to `type: bbq_hnsw`, {{es}} uses the HNSW algorithm for fast [kNN search](https://www.elastic.co/docs//solutions/search/vector/knn) on compressed vectors. With the default [oversampling](#bbq-oversampling) applied, it delivers better cost efficiency, lower latency, and improved relevance ranking, making it the best choice for large-scale similarity search.
27+
28+
:::{note}
29+
Starting in version 9.1, `bbq_hnsw` is the default indexing method for new `dense_vector` fields with greater than 384 dimensions, so you typically don’t need to specify it explicitly when creating an index.
30+
31+
Datasets with less than 384 dimensions may see less accuracy and incur a higher overhead cost related to the corrective factors, but we have observed some production datasets perform well even at fairly low dimensions including [tests on e5-small](https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch).
32+
:::
33+
34+
The following example creates an index with a `dense_vector` field configured to use the `bbq_hnsw` algorithm.
35+
36+
```console
37+
PUT bbq_hnsw-index
38+
{
39+
"mappings": {
40+
"properties": {
41+
"my_vector": {
42+
"type": "dense_vector",
43+
"dims": 64,
44+
"index": true,
45+
"index_options": {
46+
"type": "bbq_hnsw"
47+
}
48+
}
49+
}
50+
}
51+
}
52+
```
53+
54+
To change an existing index to use `bbq_hnsw`, update the field mapping:
55+
56+
```console
57+
PUT bbq_hnsw-index/_mapping
58+
{
59+
"properties": {
60+
"my_vector": {
61+
"type": "dense_vector",
62+
"dims": 64,
63+
"index": true,
64+
"index_options": {
65+
"type": "bbq_hnsw"
66+
}
67+
}
68+
}
69+
}
70+
```
71+
72+
After this change, all newly created segments will use the `bbq_hnsw` algorithm. As you add or update documents, the index will gradually convert to `bbq_hnsw`.
73+
74+
To apply `bbq_hnsw` to all vectors at once, reindex them into a new index where the `index_options` parameter's `type` is set to `bbq_hnsw`:
75+
76+
:::::{stepper}
77+
::::{step} Create a destination index
78+
```console
79+
PUT my-index-bbq
80+
{
81+
"mappings": {
82+
"properties": {
83+
"my_vector": {
84+
"type": "dense_vector",
85+
"dims": 64,
86+
"index": true,
87+
"index_options": {
88+
"type": "bbq_hnsw"
89+
}
90+
}
91+
}
92+
}
93+
}
94+
```
95+
::::
96+
97+
::::{step} Reindex the data
98+
```console
99+
POST _reindex
100+
{
101+
"source": { "index": "my-index" }, <1>
102+
"dest": { "index": "my-index-bbq" }
103+
}
104+
```
105+
1. The existing index to be reindexed into the newly created index with the `bbq_hnsw` algorithm.
106+
::::
107+
108+
:::::
109+
110+
### `bbq_flat` [bbq-flat]
111+
112+
When you set a dense vector field’s `index_options` parameter to `type: bbq_flat`, {{es}} uses the BBQ algorithm without HNSW. This option generally requires fewer computing resources and works best when the number of vectors being searched is relatively low.
113+
114+
The following example creates an index with a `dense_vector` field configured to use the `bbq_flat` algorithm.
115+
116+
```console
117+
PUT bbq_flat-index
118+
{
119+
"mappings": {
120+
"properties": {
121+
"my_vector": {
122+
"type": "dense_vector",
123+
"dims": 64,
124+
"index": true,
125+
"index_options": {
126+
"type": "bbq_flat"
127+
}
128+
}
129+
}
130+
}
131+
}
132+
```
133+
134+
## Oversampling [bbq-oversampling]
135+
136+
Oversampling is a technique used with BBQ searches to reduce the accuracy loss from compression. Compression lowers the memory footprint by over 95% and improves query latency, at the cost of decreased result accuracy. This decrease can be mitigated by oversampling during query time and reranking the top results using the full vector.
137+
138+
When you run a kNN search on a BBQ-indexed field, {{es}} automatically retrieves more candidate vectors than the number of results you request. This oversampling improves accuracy by giving the system more vectors to re-rank using their full-precision values before returning the top results.
139+
140+
```console
141+
GET bbq-index/_search
142+
{
143+
"knn": {
144+
"field": "my_vector",
145+
"query_vector": [0.12, -0.45, ...],
146+
"k": 10,
147+
"num_candidates": 100
148+
}
149+
}
150+
```
151+
152+
By default, oversampling is set to 3×, meaning if you request k:10, {{es}} retrieves 30 candidates for re-ranking. You don’t need to configure this behavior; it’s applied automatically for BBQ searches.
153+
154+
:::{note}
155+
You can change oversampling from the default 3× to another value. Refer to [Oversampling and rescoring for quantized vectors](https://www.elastic.co/docs/solutions/search/vector/knn#dense-vector-knn-search-rescoring) for details.
156+
:::
157+
158+
## Learn more [bbq-learn-more]
159+
160+
- [Better Binary Quantization (BBQ) in Lucene and {{es}}](https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch) - Learn how BBQ works, its benefits, and how it reduces memory usage while preserving search accuracy.
161+
- [Dense vector field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector) - Find code examples for using `bbq_hnsw` `index_type`.
162+
- [kNN search](https://www.elastic.co/docs/solutions/search/vector/knn) - Learn about the search algorithm that BBQ works with.

docs/reference/elasticsearch/mapping-reference/dense-vector.md

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,81 @@ PUT my-index-2
102102

103103
{{es}} uses the [HNSW algorithm](https://arxiv.org/abs/1603.09320) to support efficient kNN search. Like most kNN algorithms, HNSW is an approximate method that sacrifices result accuracy for improved speed.
104104

105+
## Accessing `dense_vector` fields in search responses
106+
```{applies_to}
107+
stack: ga 9.2
108+
serverless: ga
109+
```
110+
111+
By default, `dense_vector` fields are **not included in `_source`** in responses from the `_search`, `_msearch`, `_get`, and `_mget` APIs.
112+
This helps reduce response size and improve performance, especially in scenarios where vectors are used solely for similarity scoring and not required in the output.
113+
114+
To retrieve vector values explicitly, you can use:
115+
116+
* The `fields` option to request specific vector fields directly:
117+
118+
```console
119+
POST my-index-2/_search
120+
{
121+
"fields": ["my_vector"]
122+
}
123+
```
124+
125+
- The `_source.exclude_vectors` flag to re-enable vector inclusion in `_source` responses:
126+
127+
```console
128+
POST my-index-2/_search
129+
{
130+
"_source": {
131+
"exclude_vectors": false
132+
}
133+
}
134+
```
135+
136+
### Storage behavior and `_source`
137+
138+
By default, `dense_vector` fields are **not stored in `_source`** on disk. This is also controlled by the index setting `index.mapping.exclude_source_vectors`.
139+
This setting is enabled by default for newly created indices and can only be set at index creation time.
140+
141+
When enabled:
142+
143+
* `dense_vector` fields are removed from `_source` and the rest of the `_source` is stored as usual.
144+
* If a request includes `_source` and vector values are needed (e.g., during recovery or reindex), the vectors are rehydrated from their internal format.
145+
146+
This setting is compatible with synthetic `_source`, where the entire `_source` document is reconstructed from columnar storage. In full synthetic mode, no `_source` is stored on disk, and all fields — including vectors — are rebuilt when needed.
147+
148+
### Rehydration and precision
149+
150+
When vector values are rehydrated (e.g., for reindex, recovery, or explicit `_source` requests), they are restored from their internal format. Internally, vectors are stored at float precision, so if they were originally indexed as higher-precision types (e.g., `double` or `long`), the rehydrated values will have reduced precision. This lossy representation is intended to save space while preserving search quality.
151+
152+
### Storing original vectors in `_source`
153+
154+
If you want to preserve the original vector values exactly as they were provided, you can re-enable vector storage in `_source`:
155+
156+
```console
157+
PUT my-index-include-vectors
158+
{
159+
"settings": {
160+
"index.mapping.exclude_source_vectors": false
161+
},
162+
"mappings": {
163+
"properties": {
164+
"my_vector": {
165+
"type": "dense_vector"
166+
}
167+
}
168+
}
169+
}
170+
```
171+
172+
When this setting is disabled:
173+
174+
* `dense_vector` fields are stored as part of the `_source`, exactly as indexed.
175+
* The index will store both the original `_source` value and the internal representation used for vector search, resulting in increased storage usage.
176+
* Vectors are once again returned in `_source` by default in all relevant APIs, with no need to use `exclude_vectors` or `fields`.
177+
178+
This configuration is appropriate when full source fidelity is required, such as for auditing or round-tripping exact input values.
179+
105180
## Automatically quantize vectors for kNN search [dense-vector-quantization]
106181

107182
The `dense_vector` type supports quantization to reduce the memory footprint required when [searching](docs-content://solutions/search/vector/knn.md#approximate-knn) `float` vectors. The three following quantization strategies are supported:
@@ -266,16 +341,16 @@ $$$dense-vector-index-options$$$
266341
`type`
267342
: (Required, string) The type of kNN algorithm to use. Can be either any of:
268343
* `hnsw` - This utilizes the [HNSW algorithm](https://arxiv.org/abs/1603.09320) for scalable approximate kNN search. This supports all `element_type` values.
269-
* `int8_hnsw` - The default index type for some float vectors:
270-
271-
* {applies_to}`stack: ga 9.1` Default for float vectors with less than 384 dimensions.
344+
* `int8_hnsw` - The default index type for some float vectors:
345+
346+
* {applies_to}`stack: ga 9.1` Default for float vectors with less than 384 dimensions.
272347
* {applies_to}`stack: ga 9.0` Default for float all vectors.
273-
348+
274349
This utilizes the [HNSW algorithm](https://arxiv.org/abs/1603.09320) in addition to automatically scalar quantization for scalable approximate kNN search with `element_type` of `float`. This can reduce the memory footprint by 4x at the cost of some accuracy. See [Automatically quantize vectors for kNN search](#dense-vector-quantization).
275350
* `int4_hnsw` - This utilizes the [HNSW algorithm](https://arxiv.org/abs/1603.09320) in addition to automatically scalar quantization for scalable approximate kNN search with `element_type` of `float`. This can reduce the memory footprint by 8x at the cost of some accuracy. See [Automatically quantize vectors for kNN search](#dense-vector-quantization).
276351
* `bbq_hnsw` - This utilizes the [HNSW algorithm](https://arxiv.org/abs/1603.09320) in addition to automatically binary quantization for scalable approximate kNN search with `element_type` of `float`. This can reduce the memory footprint by 32x at the cost of accuracy. See [Automatically quantize vectors for kNN search](#dense-vector-quantization).
277-
278-
{applies_to}`stack: ga 9.1` `bbq_hnsw` is the default index type for float vectors with greater than or equal to 384 dimensions.
352+
353+
{applies_to}`stack: ga 9.1` `bbq_hnsw` is the default index type for float vectors with greater than or equal to 384 dimensions.
279354
* `flat` - This utilizes a brute-force search algorithm for exact kNN search. This supports all `element_type` values.
280355
* `int8_flat` - This utilizes a brute-force search algorithm in addition to automatically scalar quantization. Only supports `element_type` of `float`.
281356
* `int4_flat` - This utilizes a brute-force search algorithm in addition to automatically half-byte scalar quantization. Only supports `element_type` of `float`.
@@ -295,8 +370,8 @@ $$$dense-vector-index-options$$$
295370
: (Optional, object) An optional section that configures automatic vector rescoring on knn queries for the given field. Only applicable to quantized index types.
296371
:::::{dropdown} Properties of rescore_vector
297372
`oversample`
298-
: (required, float) The amount to oversample the search results by. This value should be one of the following:
299-
* Greater than `1.0` and less than `10.0`
373+
: (required, float) The amount to oversample the search results by. This value should be one of the following:
374+
* Greater than `1.0` and less than `10.0`
300375
* Exactly `0` to indicate no oversampling and rescoring should occur {applies_to}`stack: ga 9.1`
301376
: The higher the value, the more vectors will be gathered and rescored with the raw values per shard.
302377
: In case a knn query specifies a `rescore_vector` parameter, the query `rescore_vector` parameter will be used instead.

0 commit comments

Comments
 (0)