Skip to content

Commit 781c756

Browse files
authored
Fix default index options when dimensions are unset for legacy indices (#130540) (#130575)
Backport of #130572 to 9.1
1 parent e7239c0 commit 781c756

File tree

2 files changed

+65
-57
lines changed

2 files changed

+65
-57
lines changed

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.vectors/40_knn_search.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,40 @@ setup:
605605
- match: { hits.hits.0._score: $knn_score0 }
606606
- match: { hits.hits.1._score: $knn_score1 }
607607
- match: { hits.hits.2._score: $knn_score2 }
608+
609+
---
610+
"Dimensions are dynamically set":
611+
- do:
612+
indices.create:
613+
index: test_index
614+
body:
615+
mappings:
616+
properties:
617+
embedding:
618+
type: dense_vector
619+
620+
- do:
621+
index:
622+
index: test_index
623+
id: "0"
624+
body:
625+
embedding: [ 0.5, 111.3, -13.0, 14.8, -156.0 ]
626+
627+
- do:
628+
indices.get_mapping:
629+
index: test_index
630+
631+
- match: { test_index.mappings.properties.embedding.type: dense_vector }
632+
- match: { test_index.mappings.properties.embedding.dims: 5 }
633+
634+
- do:
635+
catch: bad_request
636+
index:
637+
index: test_index
638+
id: "0"
639+
body:
640+
embedding: [ 0.5, 111.3 ]
641+
608642
---
609643
"Updating dim to null is not allowed":
610644
- requires:

server/src/main/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapper.java

Lines changed: 31 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,9 @@ public Builder(String name, IndexVersion indexVersionCreated) {
327327
|| previous.updatableTo(current)
328328
);
329329
if (defaultInt8Hnsw || defaultBBQ8Hnsw) {
330-
this.indexOptions.alwaysSerialize();
330+
if (defaultBBQ8Hnsw == false || (dims != null && dims.isConfigured())) {
331+
this.indexOptions.alwaysSerialize();
332+
}
331333
}
332334
this.indexed.addValidator(v -> {
333335
if (v) {
@@ -350,21 +352,31 @@ public Builder(String name, IndexVersion indexVersionCreated) {
350352
}
351353

352354
private DenseVectorIndexOptions defaultIndexOptions(boolean defaultInt8Hnsw, boolean defaultBBQHnsw) {
353-
if (this.dims != null && this.dims.isConfigured() && elementType.getValue() == ElementType.FLOAT && this.indexed.getValue()) {
354-
if (defaultBBQHnsw && this.dims.getValue() >= BBQ_DIMS_DEFAULT_THRESHOLD) {
355-
return new BBQHnswIndexOptions(
356-
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
357-
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
358-
new RescoreVector(DEFAULT_OVERSAMPLE)
359-
);
360-
} else if (defaultInt8Hnsw) {
361-
return new Int8HnswIndexOptions(
362-
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
363-
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
364-
null,
365-
null
366-
);
367-
}
355+
if (elementType.getValue() != ElementType.FLOAT || indexed.getValue() == false) {
356+
return null;
357+
}
358+
359+
boolean dimIsConfigured = dims != null && dims.isConfigured();
360+
if (defaultBBQHnsw && dimIsConfigured == false) {
361+
// Delay selecting the default index options until dimensions are configured.
362+
// This applies only to indices that are eligible to use BBQ as the default,
363+
// since prior to this change, the default was selected eagerly.
364+
return null;
365+
}
366+
367+
if (defaultBBQHnsw && dimIsConfigured && dims.getValue() >= BBQ_DIMS_DEFAULT_THRESHOLD) {
368+
return new BBQHnswIndexOptions(
369+
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
370+
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
371+
new RescoreVector(DEFAULT_OVERSAMPLE)
372+
);
373+
} else if (defaultInt8Hnsw) {
374+
return new Int8HnswIndexOptions(
375+
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
376+
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
377+
null,
378+
null
379+
);
368380
}
369381
return null;
370382
}
@@ -2713,47 +2725,9 @@ public void parse(DocumentParserContext context) throws IOException {
27132725
}
27142726
if (fieldType().dims == null) {
27152727
int dims = fieldType().elementType.parseDimensionCount(context);
2716-
;
2717-
final boolean defaultInt8Hnsw = indexCreatedVersion.onOrAfter(IndexVersions.DEFAULT_DENSE_VECTOR_TO_INT8_HNSW);
2718-
final boolean defaultBBQ8Hnsw = indexCreatedVersion.onOrAfter(IndexVersions.DEFAULT_DENSE_VECTOR_TO_BBQ_HNSW);
2719-
DenseVectorIndexOptions denseVectorIndexOptions = fieldType().indexOptions;
2720-
if (denseVectorIndexOptions == null && fieldType().getElementType() == ElementType.FLOAT && fieldType().isIndexed()) {
2721-
if (defaultBBQ8Hnsw && dims >= BBQ_DIMS_DEFAULT_THRESHOLD) {
2722-
denseVectorIndexOptions = new BBQHnswIndexOptions(
2723-
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
2724-
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
2725-
new RescoreVector(DEFAULT_OVERSAMPLE)
2726-
);
2727-
} else if (defaultInt8Hnsw) {
2728-
denseVectorIndexOptions = new Int8HnswIndexOptions(
2729-
Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN,
2730-
Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH,
2731-
null,
2732-
null
2733-
);
2734-
}
2735-
}
2736-
if (denseVectorIndexOptions != null) {
2737-
denseVectorIndexOptions.validateDimension(dims);
2738-
}
2739-
DenseVectorFieldType updatedDenseVectorFieldType = new DenseVectorFieldType(
2740-
fieldType().name(),
2741-
indexCreatedVersion,
2742-
fieldType().elementType,
2743-
dims,
2744-
fieldType().indexed,
2745-
fieldType().similarity,
2746-
denseVectorIndexOptions,
2747-
fieldType().meta(),
2748-
fieldType().isSyntheticSource
2749-
);
2750-
Mapper update = new DenseVectorFieldMapper(
2751-
leafName(),
2752-
updatedDenseVectorFieldType,
2753-
builderParams,
2754-
denseVectorIndexOptions,
2755-
indexCreatedVersion
2756-
);
2728+
DenseVectorFieldMapper.Builder builder = (Builder) getMergeBuilder();
2729+
builder.dimensions(dims);
2730+
Mapper update = builder.build(context.createDynamicMapperBuilderContext());
27572731
context.addDynamicMapper(update);
27582732
return;
27592733
}

0 commit comments

Comments
 (0)