aboutsummaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorGeir Storli <geirst@verizonmedia.com>2020-02-18 09:52:24 +0100
committerGitHub <noreply@github.com>2020-02-18 09:52:24 +0100
commitf752e59466d042f686314aed42be59707a0766a9 (patch)
tree350db4c53183b4784c4cbf1afda8c7d5ff2a32f1 /config-model
parent7814e2aec7b3396d6a9bbc66b7b8627817a04c33 (diff)
parentd96f6d95757cbf9e51de1bbb871bc8ebfd221b55 (diff)
Merge pull request #12232 from vespa-engine/geirst/config-for-hnsw-index-on-tensor-attribute
Add support for specifying a hnsw index together with a 1-dimensional…
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/Index.java41
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java8
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/derived/IndexSchema.java12
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java8
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/document/HnswIndexParams.java60
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/fieldoperation/IndexOperation.java11
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/processing/TensorFieldProcessor.java45
-rw-r--r--config-model/src/main/javacc/SDParser.jj26
-rw-r--r--config-model/src/test/derived/advanced/attributes.cfg3
-rw-r--r--config-model/src/test/derived/array_of_struct_attribute/attributes.cfg6
-rw-r--r--config-model/src/test/derived/attributeprefetch/attributes.cfg54
-rw-r--r--config-model/src/test/derived/attributes/attributes.cfg54
-rw-r--r--config-model/src/test/derived/complex/attributes.cfg27
-rw-r--r--config-model/src/test/derived/hnsw_index/attributes.cfg24
-rw-r--r--config-model/src/test/derived/hnsw_index/ilscripts.cfg5
-rw-r--r--config-model/src/test/derived/hnsw_index/test.sd13
-rw-r--r--config-model/src/test/derived/imported_position_field/attributes.cfg90
-rw-r--r--config-model/src/test/derived/imported_struct_fields/attributes.cfg360
-rw-r--r--config-model/src/test/derived/importedfields/attributes.cfg24
-rw-r--r--config-model/src/test/derived/inheritance/attributes.cfg9
-rw-r--r--config-model/src/test/derived/inheritfromparent/attributes.cfg3
-rw-r--r--config-model/src/test/derived/map_attribute/attributes.cfg9
-rw-r--r--config-model/src/test/derived/map_of_struct_attribute/attributes.cfg15
-rw-r--r--config-model/src/test/derived/music/attributes.cfg33
-rw-r--r--config-model/src/test/derived/newrank/attributes.cfg30
-rw-r--r--config-model/src/test/derived/predicate_attribute/attributes.cfg3
-rw-r--r--config-model/src/test/derived/prefixexactattribute/attributes.cfg6
-rw-r--r--config-model/src/test/derived/reference_fields/attributes.cfg9
-rw-r--r--config-model/src/test/derived/sorting/attributes.cfg9
-rw-r--r--config-model/src/test/derived/tensor/attributes.cfg15
-rw-r--r--config-model/src/test/derived/types/attributes.cfg39
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java5
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorFieldTestCase.java79
33 files changed, 898 insertions, 237 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/Index.java b/config-model/src/main/java/com/yahoo/searchdefinition/Index.java
index e46db1d1b5f..90f061d933d 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/Index.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/Index.java
@@ -2,6 +2,7 @@
package com.yahoo.searchdefinition;
import com.yahoo.searchdefinition.document.BooleanIndexDefinition;
+import com.yahoo.searchdefinition.document.HnswIndexParams;
import com.yahoo.searchdefinition.document.RankType;
import com.yahoo.searchdefinition.document.Stemming;
@@ -9,8 +10,11 @@ import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
+
/**
* An index definition in a search definition.
* Two indices are equal if they have the same name and the same settings, except
@@ -57,6 +61,8 @@ public class Index implements Cloneable, Serializable {
/** The boolean index definition, if set */
private BooleanIndexDefinition boolIndex;
+ private Optional<HnswIndexParams> hnswIndexParams;
+
/** Whether the posting lists of this index field should have interleaved features (num occs, field length) in document id stream. */
private boolean interleavedFeatures = false;
@@ -115,20 +121,25 @@ public class Index implements Cloneable, Serializable {
}
@Override
- public int hashCode() {
- return name.hashCode() + ( prefix ? 17 : 0 );
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Index index = (Index) o;
+ return prefix == index.prefix &&
+ normalized == index.normalized &&
+ interleavedFeatures == index.interleavedFeatures &&
+ Objects.equals(name, index.name) &&
+ rankType == index.rankType &&
+ Objects.equals(aliases, index.aliases) &&
+ stemming == index.stemming &&
+ type == index.type &&
+ Objects.equals(boolIndex, index.boolIndex) &&
+ Objects.equals(hnswIndexParams, index.hnswIndexParams);
}
@Override
- public boolean equals(Object object) {
- if ( ! (object instanceof Index)) return false;
-
- Index other=(Index)object;
- return
- this.name.equals(other.name) &&
- this.prefix==other.prefix &&
- this.stemming==other.stemming &&
- this.normalized==other.normalized;
+ public int hashCode() {
+ return Objects.hash(name, rankType, prefix, aliases, stemming, normalized, type, boolIndex, hnswIndexParams, interleavedFeatures);
}
public String toString() {
@@ -176,6 +187,14 @@ public class Index implements Cloneable, Serializable {
boolIndex = def;
}
+ public Optional<HnswIndexParams> getHnswIndexParams() {
+ return hnswIndexParams;
+ }
+
+ public void setHnswIndexParams(HnswIndexParams params) {
+ hnswIndexParams = Optional.of(params);
+ }
+
public void setInterleavedFeatures(boolean value) {
interleavedFeatures = value;
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java
index 76dff404568..8de8b239c93 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java
@@ -240,6 +240,14 @@ public class AttributeFields extends Derived implements AttributesConfig.Produce
aaB.tensortype(attribute.tensorType().get().toString());
}
aaB.imported(imported);
+ if (attribute.hnswIndexParams().isPresent()) {
+ var ib = new AttributesConfig.Attribute.Index.Builder();
+ var params = attribute.hnswIndexParams().get();
+ ib.hnsw.enabled(true);
+ ib.hnsw.maxlinkspernode(params.maxLinksPerNode());
+ ib.hnsw.neighborstoexploreatinsert(params.neighborsToExploreAtInsert());
+ aaB.index(ib);
+ }
return aaB;
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/IndexSchema.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/IndexSchema.java
index d8773063053..39a67a69575 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/IndexSchema.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/IndexSchema.java
@@ -5,6 +5,7 @@ import com.yahoo.document.ArrayDataType;
import com.yahoo.document.DataType;
import com.yahoo.document.Field;
import com.yahoo.document.StructuredDataType;
+import com.yahoo.document.TensorDataType;
import com.yahoo.document.WeightedSetDataType;
import com.yahoo.searchdefinition.Search;
import com.yahoo.searchdefinition.document.BooleanIndexDefinition;
@@ -20,7 +21,7 @@ import java.util.List;
import java.util.Map;
/**
- * Deriver of indexschema config containing information of all index fields with name and data type.
+ * Deriver of indexschema config containing information of all text index fields with name and data type.
*
* @author geirst
*/
@@ -44,9 +45,14 @@ public class IndexSchema extends Derived implements IndexschemaConfig.Producer {
super.derive(search);
}
+ private boolean isTensorField(ImmutableSDField field) {
+ return field.getDataType() instanceof TensorDataType;
+ }
+
private void deriveIndexFields(ImmutableSDField field, Search search) {
- if (!field.doesIndexing() &&
- !field.isIndexStructureField())
+ // Note: Indexes for tensor fields are NOT part of the index schema for text fields.
+ if ((!field.doesIndexing() && !field.isIndexStructureField()) ||
+ isTensorField(field))
{
return;
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java
index fbcaf2a3a80..9ed5e4ca2de 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java
@@ -66,6 +66,8 @@ public final class Attribute implements Cloneable, Serializable {
/** This is set if the type of this is REFERENCE */
private final Optional<StructuredDataType> referenceDocumentType;
+ private Optional<HnswIndexParams> hnswIndexParams;
+
private boolean isPosition = false;
private final Sorting sorting = new Sorting();
@@ -150,6 +152,7 @@ public final class Attribute implements Cloneable, Serializable {
setCollectionType(collectionType);
this.tensorType = tensorType;
this.referenceDocumentType = referenceDocumentType;
+ this.hnswIndexParams = Optional.empty();
}
public Attribute convertToArray() {
@@ -194,6 +197,7 @@ public final class Attribute implements Cloneable, Serializable {
public double densePostingListThreshold() { return densePostingListThreshold; }
public Optional<TensorType> tensorType() { return tensorType; }
public Optional<StructuredDataType> referenceDocumentType() { return referenceDocumentType; }
+ public Optional<HnswIndexParams> hnswIndexParams() { return hnswIndexParams; }
public Sorting getSorting() { return sorting; }
@@ -217,6 +221,7 @@ public final class Attribute implements Cloneable, Serializable {
public void setUpperBound(long upperBound) { this.upperBound = upperBound; }
public void setDensePostingListThreshold(double threshold) { this.densePostingListThreshold = threshold; }
public void setTensorType(TensorType tensorType) { this.tensorType = Optional.of(tensorType); }
+ public void setHnswIndexParams(HnswIndexParams params) { this.hnswIndexParams = Optional.of(params); }
public String getName() { return name; }
public Type getType() { return type; }
@@ -335,7 +340,7 @@ public final class Attribute implements Cloneable, Serializable {
public int hashCode() {
return Objects.hash(
name, type, collectionType, sorting, isPrefetch(), fastAccess, removeIfZero, createIfNonExistent,
- isPosition, huge, enableBitVectors, enableOnlyBitVector, tensorType, referenceDocumentType);
+ isPosition, huge, enableBitVectors, enableOnlyBitVector, tensorType, referenceDocumentType, hnswIndexParams);
}
@Override
@@ -362,6 +367,7 @@ public final class Attribute implements Cloneable, Serializable {
if ( ! this.sorting.equals(other.sorting)) return false;
if (!this.tensorType.equals(other.tensorType)) return false;
if (!this.referenceDocumentType.equals(other.referenceDocumentType)) return false;
+ if (!this.hnswIndexParams.equals(other.hnswIndexParams)) return false;
return true;
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/HnswIndexParams.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/HnswIndexParams.java
new file mode 100644
index 00000000000..70d0df8be7f
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/HnswIndexParams.java
@@ -0,0 +1,60 @@
+// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.searchdefinition.document;
+
+import java.util.OptionalInt;
+
+/**
+ * Configuration parameters for a hnsw index used together with a 1-dimensional indexed tensor for approximate nearest neighbor search.
+ *
+ * @author geirst
+ */
+public class HnswIndexParams {
+
+ public static final int DEFAULT_MAX_LINKS_PER_NODE = 16;
+ public static final int DEFAULT_NEIGHBORS_TO_EXPLORE_AT_INSERT = 200;
+
+ private final OptionalInt maxLinksPerNode;
+ private final OptionalInt neighborsToExploreAtInsert;
+
+ public static class Builder {
+ private OptionalInt maxLinksPerNode = OptionalInt.empty();
+ private OptionalInt neighborsToExploreAtInsert = OptionalInt.empty();
+
+ public void setMaxLinksPerNode(int value) {
+ maxLinksPerNode = OptionalInt.of(value);
+ }
+ public void setNeighborsToExploreAtInsert(int value) {
+ neighborsToExploreAtInsert = OptionalInt.of(value);
+ }
+ public HnswIndexParams build() {
+ return new HnswIndexParams(maxLinksPerNode, neighborsToExploreAtInsert);
+ }
+ }
+
+ public HnswIndexParams() {
+ this.maxLinksPerNode = OptionalInt.empty();
+ this.neighborsToExploreAtInsert = OptionalInt.empty();
+ }
+
+ public HnswIndexParams(OptionalInt maxLinksPerNode, OptionalInt neighborsToExploreAtInsert) {
+ this.maxLinksPerNode = maxLinksPerNode;
+ this.neighborsToExploreAtInsert = neighborsToExploreAtInsert;
+ }
+
+ /**
+ * Creates a new instance where values from the given parameter instance are used where they are present,
+ * otherwise we use values from this.
+ */
+ public HnswIndexParams overrideFrom(HnswIndexParams rhs) {
+ return new HnswIndexParams(rhs.maxLinksPerNode.isPresent() ? rhs.maxLinksPerNode : maxLinksPerNode,
+ rhs.neighborsToExploreAtInsert.isPresent() ? rhs.neighborsToExploreAtInsert : neighborsToExploreAtInsert);
+ }
+
+ public int maxLinksPerNode() {
+ return maxLinksPerNode.orElse(DEFAULT_MAX_LINKS_PER_NODE);
+ }
+
+ public int neighborsToExploreAtInsert() {
+ return neighborsToExploreAtInsert.orElse(DEFAULT_NEIGHBORS_TO_EXPLORE_AT_INSERT);
+ }
+}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/fieldoperation/IndexOperation.java b/config-model/src/main/java/com/yahoo/searchdefinition/fieldoperation/IndexOperation.java
index 39f543c7db3..7f9da28b9ca 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/fieldoperation/IndexOperation.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/fieldoperation/IndexOperation.java
@@ -4,6 +4,7 @@ package com.yahoo.searchdefinition.fieldoperation;
import com.yahoo.searchdefinition.Index;
import com.yahoo.searchdefinition.Index.Type;
import com.yahoo.searchdefinition.document.BooleanIndexDefinition;
+import com.yahoo.searchdefinition.document.HnswIndexParams;
import com.yahoo.searchdefinition.document.SDField;
import com.yahoo.searchdefinition.document.Stemming;
@@ -31,6 +32,8 @@ public class IndexOperation implements FieldOperation {
private OptionalDouble densePostingListThreshold = OptionalDouble.empty();
private Optional<Boolean> enableBm25 = Optional.empty();
+ private Optional<HnswIndexParams.Builder> hnswIndexParams = Optional.empty();
+
public String getIndexName() {
return indexName;
}
@@ -91,6 +94,9 @@ public class IndexOperation implements FieldOperation {
if (enableBm25.isPresent()) {
index.setInterleavedFeatures(enableBm25.get());
}
+ if (hnswIndexParams.isPresent()) {
+ index.setHnswIndexParams(hnswIndexParams.get().build());
+ }
}
public Type getType() {
@@ -116,8 +122,13 @@ public class IndexOperation implements FieldOperation {
public void setDensePostingListThreshold(double densePostingListThreshold) {
this.densePostingListThreshold = OptionalDouble.of(densePostingListThreshold);
}
+
public void setEnableBm25(boolean value) {
enableBm25 = Optional.of(value);
}
+ public void setHnswIndexParams(HnswIndexParams.Builder params) {
+ this.hnswIndexParams = Optional.of(params);
+ }
+
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/processing/TensorFieldProcessor.java b/config-model/src/main/java/com/yahoo/searchdefinition/processing/TensorFieldProcessor.java
index 8e54d7c00d6..9cd7fb24e42 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/processing/TensorFieldProcessor.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/processing/TensorFieldProcessor.java
@@ -6,7 +6,8 @@ import com.yahoo.document.CollectionDataType;
import com.yahoo.document.TensorDataType;
import com.yahoo.searchdefinition.RankProfileRegistry;
import com.yahoo.searchdefinition.Search;
-import com.yahoo.searchdefinition.document.Attribute;
+import com.yahoo.searchdefinition.document.HnswIndexParams;
+import com.yahoo.searchdefinition.document.ImmutableSDField;
import com.yahoo.searchdefinition.document.SDField;
import com.yahoo.vespa.model.container.search.QueryProfiles;
@@ -25,10 +26,11 @@ public class TensorFieldProcessor extends Processor {
public void process(boolean validate, boolean documentsOnly) {
if ( ! validate) return;
- for (SDField field : search.allConcreteFields()) {
+ for (var field : search.allConcreteFields()) {
if ( field.getDataType() instanceof TensorDataType ) {
validateIndexingScripsForTensorField(field);
validateAttributeSettingForTensorField(field);
+ processIndexSettingsForTensorField(field);
}
else if (field.getDataType() instanceof CollectionDataType){
validateDataTypeForCollectionField(field);
@@ -37,20 +39,53 @@ public class TensorFieldProcessor extends Processor {
}
private void validateIndexingScripsForTensorField(SDField field) {
- if (field.doesIndexing()) {
- fail(search, field, "A field of type 'tensor' cannot be specified as an 'index' field.");
+ if (field.doesIndexing() && !isTensorTypeThatSupportsHnswIndex(field)) {
+ fail(search, field, "A tensor of type '" + tensorTypeToString(field) + "' does not support having an 'index'. " +
+ "Currently, only tensors with 1 indexed dimension supports that.");
}
}
+ private boolean isTensorTypeThatSupportsHnswIndex(ImmutableSDField field) {
+ var type = ((TensorDataType)field.getDataType()).getTensorType();
+ // Tensors with 1 indexed dimension supports a hnsw index (used for approximate nearest neighbor search).
+ if ((type.dimensions().size() == 1) &&
+ type.dimensions().get(0).isIndexed()) {
+ return true;
+ }
+ return false;
+ }
+
+ private String tensorTypeToString(ImmutableSDField field) {
+ return ((TensorDataType)field.getDataType()).getTensorType().toString();
+ }
+
private void validateAttributeSettingForTensorField(SDField field) {
if (field.doesAttributing()) {
- Attribute attribute = field.getAttributes().get(field.getName());
+ var attribute = field.getAttributes().get(field.getName());
if (attribute != null && attribute.isFastSearch()) {
fail(search, field, "An attribute of type 'tensor' cannot be 'fast-search'.");
}
}
}
+ private void processIndexSettingsForTensorField(SDField field) {
+ if (!field.doesIndexing()) {
+ return;
+ }
+ if (isTensorTypeThatSupportsHnswIndex(field)) {
+ if (!field.doesAttributing()) {
+ fail(search, field, "A tensor that has an index must also be an attribute.");
+ }
+ var index = field.getIndex(field.getName());
+ // TODO: Calculate default params based on tensor dimension size
+ var params = new HnswIndexParams();
+ if (index != null && index.getHnswIndexParams().isPresent()) {
+ params = params.overrideFrom(index.getHnswIndexParams().get());
+ }
+ field.getAttribute().setHnswIndexParams(params);
+ }
+ }
+
private void validateDataTypeForCollectionField(SDField field) {
if (((CollectionDataType)field.getDataType()).getNestedType() instanceof TensorDataType)
fail(search, field, "A field with collection type of tensor is not supported. Use simple type 'tensor' instead.");
diff --git a/config-model/src/main/javacc/SDParser.jj b/config-model/src/main/javacc/SDParser.jj
index eb7d7763cd1..0cfd13f2a9c 100644
--- a/config-model/src/main/javacc/SDParser.jj
+++ b/config-model/src/main/javacc/SDParser.jj
@@ -332,6 +332,9 @@ TOKEN :
| < UPPERBOUND: "upper-bound" >
| < DENSEPOSTINGLISTTHRESHOLD: "dense-posting-list-threshold" >
| < ENABLE_BM25: "enable-bm25" >
+| < HNSW: "hnsw" >
+| < MAXLINKSPERNODE: "max-links-per-node" >
+| < NEIGHBORSTOEXPLOREATINSERT: "neighbors-to-explore-at-insert" >
| < SUMMARYFEATURES_SL: "summary-features" (" ")* ":" (~["}","\n"])* ("\n")? >
| < SUMMARYFEATURES_ML: "summary-features" (<SEARCHLIB_SKIP>)? "{" (~["}"])* "}" >
| < RANKFEATURES_SL: "rank-features" (" ")* ":" (~["}","\n"])* ("\n")? >
@@ -1811,10 +1814,33 @@ Object indexBody(IndexOperation index) :
| <UPPERBOUND> <COLON> num = consumeLong() { index.setUpperBound(num); }
| <DENSEPOSTINGLISTTHRESHOLD> <COLON> threshold = consumeFloat() { index.setDensePostingListThreshold(threshold); }
| <ENABLE_BM25> { index.setEnableBm25(true); }
+ | hnswIndex(index) { }
)
{ return null; }
}
+void hnswIndex(IndexOperation index) :
+{
+ HnswIndexParams.Builder params = new HnswIndexParams.Builder();
+}
+{
+ ( LOOKAHEAD(<HNSW> lbrace())
+ <HNSW> ( (lbrace() (hnswIndexBody(params) (<NL>)*)* <RBRACE>) ) |
+ <HNSW> )
+ {
+ index.setHnswIndexParams(params);
+ }
+}
+
+void hnswIndexBody(HnswIndexParams.Builder params) :
+{
+ int num;
+}
+{
+ ( <MAXLINKSPERNODE> <COLON> num = integer() { params.setMaxLinksPerNode(num); }
+ | <NEIGHBORSTOEXPLOREATINSERT> <COLON> num = integer() { params.setNeighborsToExploreAtInsert(num); } )
+}
+
/**
* Consumes a constant block of a search element.
*
diff --git a/config-model/src/test/derived/advanced/attributes.cfg b/config-model/src/test/derived/advanced/attributes.cfg
index 97f480745cf..cf8644ebe83 100644
--- a/config-model/src/test/derived/advanced/attributes.cfg
+++ b/config-model/src/test/derived/advanced/attributes.cfg
@@ -19,3 +19,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg b/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg
index 56fd15f9f5d..29d5dd92043 100644
--- a/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg
+++ b/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "elem_array.weight"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -40,3 +43,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/attributeprefetch/attributes.cfg b/config-model/src/test/derived/attributeprefetch/attributes.cfg
index 022bdbd31a4..773f796ed59 100644
--- a/config-model/src/test/derived/attributeprefetch/attributes.cfg
+++ b/config-model/src/test/derived/attributeprefetch/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multibyte"
attribute[].datatype INT8
attribute[].collectiontype ARRAY
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wsbyte"
attribute[].datatype INT8
attribute[].collectiontype WEIGHTEDSET
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "singleint"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multiint"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wsint"
attribute[].datatype INT32
attribute[].collectiontype WEIGHTEDSET
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "singlelong"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multilong"
attribute[].datatype INT64
attribute[].collectiontype ARRAY
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wslong"
attribute[].datatype INT64
attribute[].collectiontype WEIGHTEDSET
@@ -187,6 +211,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "singlefloat"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -208,6 +235,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multifloat"
attribute[].datatype FLOAT
attribute[].collectiontype ARRAY
@@ -229,6 +259,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wsfloat"
attribute[].datatype FLOAT
attribute[].collectiontype WEIGHTEDSET
@@ -250,6 +283,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "singledouble"
attribute[].datatype DOUBLE
attribute[].collectiontype SINGLE
@@ -271,6 +307,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multidouble"
attribute[].datatype DOUBLE
attribute[].collectiontype ARRAY
@@ -292,6 +331,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wsdouble"
attribute[].datatype DOUBLE
attribute[].collectiontype WEIGHTEDSET
@@ -313,6 +355,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "singlestring"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -334,6 +379,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "multistring"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -355,6 +403,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "wsstring"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -376,3 +427,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/attributes/attributes.cfg b/config-model/src/test/derived/attributes/attributes.cfg
index 7a21001a9ed..e3faf7662f4 100644
--- a/config-model/src/test/derived/attributes/attributes.cfg
+++ b/config-model/src/test/derived/attributes/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a2"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a3"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a5"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a6"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b1"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b2"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b3"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b4"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -187,6 +211,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b5"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -208,6 +235,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b6"
attribute[].datatype INT64
attribute[].collectiontype ARRAY
@@ -229,6 +259,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b7"
attribute[].datatype DOUBLE
attribute[].collectiontype WEIGHTEDSET
@@ -250,6 +283,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a9"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -271,6 +307,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a10"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -292,6 +331,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a11"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -313,6 +355,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a12"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -334,6 +379,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a7_arr"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -355,6 +403,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "a8_arr"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -376,3 +427,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/complex/attributes.cfg b/config-model/src/test/derived/complex/attributes.cfg
index dda746da5b4..b4971487bd1 100644
--- a/config-model/src/test/derived/complex/attributes.cfg
+++ b/config-model/src/test/derived/complex/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "fleeting"
attribute[].datatype FLOAT
attribute[].collectiontype ARRAY
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "fleeting2"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "foundat"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "collapseby"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "ts"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "combineda"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "year_arr"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "year_sub"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -187,3 +211,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/hnsw_index/attributes.cfg b/config-model/src/test/derived/hnsw_index/attributes.cfg
new file mode 100644
index 00000000000..27c9f1e0d13
--- /dev/null
+++ b/config-model/src/test/derived/hnsw_index/attributes.cfg
@@ -0,0 +1,24 @@
+attribute[].name "t1"
+attribute[].datatype TENSOR
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype "tensor(x[128])"
+attribute[].imported false
+attribute[].index.hnsw.enabled true
+attribute[].index.hnsw.maxlinkspernode 32
+attribute[].index.hnsw.neighborstoexploreatinsert 300
diff --git a/config-model/src/test/derived/hnsw_index/ilscripts.cfg b/config-model/src/test/derived/hnsw_index/ilscripts.cfg
new file mode 100644
index 00000000000..e9fc265ca67
--- /dev/null
+++ b/config-model/src/test/derived/hnsw_index/ilscripts.cfg
@@ -0,0 +1,5 @@
+maxtermoccurrences 100
+fieldmatchmaxlength 1000000
+ilscript[].doctype "test"
+ilscript[].docfield[] "t1"
+ilscript[].content[] "clear_state | guard { input t1 | attribute t1 | index t1; }"
diff --git a/config-model/src/test/derived/hnsw_index/test.sd b/config-model/src/test/derived/hnsw_index/test.sd
new file mode 100644
index 00000000000..03ede04208b
--- /dev/null
+++ b/config-model/src/test/derived/hnsw_index/test.sd
@@ -0,0 +1,13 @@
+search test {
+ document test {
+ field t1 type tensor(x[128]) {
+ indexing: attribute | index
+ index {
+ hnsw {
+ max-links-per-node: 32
+ neighbors-to-explore-at-insert: 300
+ }
+ }
+ }
+ }
+}
diff --git a/config-model/src/test/derived/imported_position_field/attributes.cfg b/config-model/src/test/derived/imported_position_field/attributes.cfg
index db2280a7846..5427e856df0 100644
--- a/config-model/src/test/derived/imported_position_field/attributes.cfg
+++ b/config-model/src/test/derived/imported_position_field/attributes.cfg
@@ -1,42 +1,48 @@
-attribute[0].name "parent_ref"
-attribute[0].datatype REFERENCE
-attribute[0].collectiontype SINGLE
-attribute[0].removeifzero false
-attribute[0].createifnonexistent false
-attribute[0].fastsearch false
-attribute[0].huge false
-attribute[0].ismutable false
-attribute[0].sortascending true
-attribute[0].sortfunction UCA
-attribute[0].sortstrength PRIMARY
-attribute[0].sortlocale ""
-attribute[0].enablebitvectors false
-attribute[0].enableonlybitvector false
-attribute[0].fastaccess false
-attribute[0].arity 8
-attribute[0].lowerbound -9223372036854775808
-attribute[0].upperbound 9223372036854775807
-attribute[0].densepostinglistthreshold 0.4
-attribute[0].tensortype ""
-attribute[0].imported false
-attribute[1].name "my_pos_zcurve"
-attribute[1].datatype INT64
-attribute[1].collectiontype SINGLE
-attribute[1].removeifzero false
-attribute[1].createifnonexistent false
-attribute[1].fastsearch true
-attribute[1].huge false
-attribute[1].ismutable false
-attribute[1].sortascending true
-attribute[1].sortfunction UCA
-attribute[1].sortstrength PRIMARY
-attribute[1].sortlocale ""
-attribute[1].enablebitvectors false
-attribute[1].enableonlybitvector false
-attribute[1].fastaccess false
-attribute[1].arity 8
-attribute[1].lowerbound -9223372036854775808
-attribute[1].upperbound 9223372036854775807
-attribute[1].densepostinglistthreshold 0.4
-attribute[1].tensortype ""
-attribute[1].imported true \ No newline at end of file
+attribute[].name "parent_ref"
+attribute[].datatype REFERENCE
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_pos_zcurve"
+attribute[].datatype INT64
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch true
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/imported_struct_fields/attributes.cfg b/config-model/src/test/derived/imported_struct_fields/attributes.cfg
index ce6ff5e54ae..e1969e991dd 100644
--- a/config-model/src/test/derived/imported_struct_fields/attributes.cfg
+++ b/config-model/src/test/derived/imported_struct_fields/attributes.cfg
@@ -1,168 +1,192 @@
-attribute[0].name "parent_ref"
-attribute[0].datatype REFERENCE
-attribute[0].collectiontype SINGLE
-attribute[0].removeifzero false
-attribute[0].createifnonexistent false
-attribute[0].fastsearch false
-attribute[0].huge false
-attribute[0].ismutable false
-attribute[0].sortascending true
-attribute[0].sortfunction UCA
-attribute[0].sortstrength PRIMARY
-attribute[0].sortlocale ""
-attribute[0].enablebitvectors false
-attribute[0].enableonlybitvector false
-attribute[0].fastaccess false
-attribute[0].arity 8
-attribute[0].lowerbound -9223372036854775808
-attribute[0].upperbound 9223372036854775807
-attribute[0].densepostinglistthreshold 0.4
-attribute[0].tensortype ""
-attribute[0].imported false
-attribute[1].name "my_elem_array.name"
-attribute[1].datatype STRING
-attribute[1].collectiontype SINGLE
-attribute[1].removeifzero false
-attribute[1].createifnonexistent false
-attribute[1].fastsearch true
-attribute[1].huge false
-attribute[1].ismutable false
-attribute[1].sortascending true
-attribute[1].sortfunction UCA
-attribute[1].sortstrength PRIMARY
-attribute[1].sortlocale ""
-attribute[1].enablebitvectors false
-attribute[1].enableonlybitvector false
-attribute[1].fastaccess false
-attribute[1].arity 8
-attribute[1].lowerbound -9223372036854775808
-attribute[1].upperbound 9223372036854775807
-attribute[1].densepostinglistthreshold 0.4
-attribute[1].tensortype ""
-attribute[1].imported true
-attribute[2].name "my_elem_array.weight"
-attribute[2].datatype INT32
-attribute[2].collectiontype SINGLE
-attribute[2].removeifzero false
-attribute[2].createifnonexistent false
-attribute[2].fastsearch false
-attribute[2].huge false
-attribute[2].ismutable false
-attribute[2].sortascending true
-attribute[2].sortfunction UCA
-attribute[2].sortstrength PRIMARY
-attribute[2].sortlocale ""
-attribute[2].enablebitvectors false
-attribute[2].enableonlybitvector false
-attribute[2].fastaccess false
-attribute[2].arity 8
-attribute[2].lowerbound -9223372036854775808
-attribute[2].upperbound 9223372036854775807
-attribute[2].densepostinglistthreshold 0.4
-attribute[2].tensortype ""
-attribute[2].imported true
-attribute[3].name "my_elem_map.key"
-attribute[3].datatype STRING
-attribute[3].collectiontype SINGLE
-attribute[3].removeifzero false
-attribute[3].createifnonexistent false
-attribute[3].fastsearch true
-attribute[3].huge false
-attribute[3].ismutable false
-attribute[3].sortascending true
-attribute[3].sortfunction UCA
-attribute[3].sortstrength PRIMARY
-attribute[3].sortlocale ""
-attribute[3].enablebitvectors false
-attribute[3].enableonlybitvector false
-attribute[3].fastaccess false
-attribute[3].arity 8
-attribute[3].lowerbound -9223372036854775808
-attribute[3].upperbound 9223372036854775807
-attribute[3].densepostinglistthreshold 0.4
-attribute[3].tensortype ""
-attribute[3].imported true
-attribute[4].name "my_elem_map.value.name"
-attribute[4].datatype STRING
-attribute[4].collectiontype SINGLE
-attribute[4].removeifzero false
-attribute[4].createifnonexistent false
-attribute[4].fastsearch true
-attribute[4].huge false
-attribute[4].ismutable false
-attribute[4].sortascending true
-attribute[4].sortfunction UCA
-attribute[4].sortstrength PRIMARY
-attribute[4].sortlocale ""
-attribute[4].enablebitvectors false
-attribute[4].enableonlybitvector false
-attribute[4].fastaccess false
-attribute[4].arity 8
-attribute[4].lowerbound -9223372036854775808
-attribute[4].upperbound 9223372036854775807
-attribute[4].densepostinglistthreshold 0.4
-attribute[4].tensortype ""
-attribute[4].imported true
-attribute[5].name "my_elem_map.value.weight"
-attribute[5].datatype INT32
-attribute[5].collectiontype SINGLE
-attribute[5].removeifzero false
-attribute[5].createifnonexistent false
-attribute[5].fastsearch false
-attribute[5].huge false
-attribute[5].ismutable false
-attribute[5].sortascending true
-attribute[5].sortfunction UCA
-attribute[5].sortstrength PRIMARY
-attribute[5].sortlocale ""
-attribute[5].enablebitvectors false
-attribute[5].enableonlybitvector false
-attribute[5].fastaccess false
-attribute[5].arity 8
-attribute[5].lowerbound -9223372036854775808
-attribute[5].upperbound 9223372036854775807
-attribute[5].densepostinglistthreshold 0.4
-attribute[5].tensortype ""
-attribute[5].imported true
-attribute[6].name "my_str_int_map.key"
-attribute[6].datatype STRING
-attribute[6].collectiontype SINGLE
-attribute[6].removeifzero false
-attribute[6].createifnonexistent false
-attribute[6].fastsearch true
-attribute[6].huge false
-attribute[6].ismutable false
-attribute[6].sortascending true
-attribute[6].sortfunction UCA
-attribute[6].sortstrength PRIMARY
-attribute[6].sortlocale ""
-attribute[6].enablebitvectors false
-attribute[6].enableonlybitvector false
-attribute[6].fastaccess false
-attribute[6].arity 8
-attribute[6].lowerbound -9223372036854775808
-attribute[6].upperbound 9223372036854775807
-attribute[6].densepostinglistthreshold 0.4
-attribute[6].tensortype ""
-attribute[6].imported true
-attribute[7].name "my_str_int_map.value"
-attribute[7].datatype INT32
-attribute[7].collectiontype SINGLE
-attribute[7].removeifzero false
-attribute[7].createifnonexistent false
-attribute[7].fastsearch false
-attribute[7].huge false
-attribute[7].ismutable false
-attribute[7].sortascending true
-attribute[7].sortfunction UCA
-attribute[7].sortstrength PRIMARY
-attribute[7].sortlocale ""
-attribute[7].enablebitvectors false
-attribute[7].enableonlybitvector false
-attribute[7].fastaccess false
-attribute[7].arity 8
-attribute[7].lowerbound -9223372036854775808
-attribute[7].upperbound 9223372036854775807
-attribute[7].densepostinglistthreshold 0.4
-attribute[7].tensortype ""
-attribute[7].imported true \ No newline at end of file
+attribute[].name "parent_ref"
+attribute[].datatype REFERENCE
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_elem_array.name"
+attribute[].datatype STRING
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch true
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_elem_array.weight"
+attribute[].datatype INT32
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_elem_map.key"
+attribute[].datatype STRING
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch true
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_elem_map.value.name"
+attribute[].datatype STRING
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch true
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_elem_map.value.weight"
+attribute[].datatype INT32
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_str_int_map.key"
+attribute[].datatype STRING
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch true
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
+attribute[].name "my_str_int_map.value"
+attribute[].datatype INT32
+attribute[].collectiontype SINGLE
+attribute[].removeifzero false
+attribute[].createifnonexistent false
+attribute[].fastsearch false
+attribute[].huge false
+attribute[].ismutable false
+attribute[].sortascending true
+attribute[].sortfunction UCA
+attribute[].sortstrength PRIMARY
+attribute[].sortlocale ""
+attribute[].enablebitvectors false
+attribute[].enableonlybitvector false
+attribute[].fastaccess false
+attribute[].arity 8
+attribute[].lowerbound -9223372036854775808
+attribute[].upperbound 9223372036854775807
+attribute[].densepostinglistthreshold 0.4
+attribute[].tensortype ""
+attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/importedfields/attributes.cfg b/config-model/src/test/derived/importedfields/attributes.cfg
index 15b1771a2e8..168c9bd4659 100644
--- a/config-model/src/test/derived/importedfields/attributes.cfg
+++ b/config-model/src/test/derived/importedfields/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b_ref"
attribute[].datatype REFERENCE
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "b_ref_with_summary"
attribute[].datatype REFERENCE
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "my_int_field"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "my_string_field"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "my_int_array_field"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "my_int_wset_field"
attribute[].datatype INT32
attribute[].collectiontype WEIGHTEDSET
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "my_ancient_int_field"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -166,3 +187,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported true
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/inheritance/attributes.cfg b/config-model/src/test/derived/inheritance/attributes.cfg
index 4a081edbf54..05a980a8347 100644
--- a/config-model/src/test/derived/inheritance/attributes.cfg
+++ b/config-model/src/test/derived/inheritance/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "overridden"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "onlymother"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -61,3 +67,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/inheritfromparent/attributes.cfg b/config-model/src/test/derived/inheritfromparent/attributes.cfg
index 13f59d4925f..9f01b6c45ce 100644
--- a/config-model/src/test/derived/inheritfromparent/attributes.cfg
+++ b/config-model/src/test/derived/inheritfromparent/attributes.cfg
@@ -19,3 +19,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/map_attribute/attributes.cfg b/config-model/src/test/derived/map_attribute/attributes.cfg
index 8901acf63d1..28cb551cced 100644
--- a/config-model/src/test/derived/map_attribute/attributes.cfg
+++ b/config-model/src/test/derived/map_attribute/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "str_map.value"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "int_map.key"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -61,3 +67,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/map_of_struct_attribute/attributes.cfg b/config-model/src/test/derived/map_of_struct_attribute/attributes.cfg
index 665edcdf45d..caae49a0252 100644
--- a/config-model/src/test/derived/map_of_struct_attribute/attributes.cfg
+++ b/config-model/src/test/derived/map_of_struct_attribute/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "str_elem_map.value.name"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "str_elem_map.value.weight"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "int_elem_map.key"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "int_elem_map.value.name"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -103,3 +115,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/music/attributes.cfg b/config-model/src/test/derived/music/attributes.cfg
index 7f9592dafc8..a045a532965 100644
--- a/config-model/src/test/derived/music/attributes.cfg
+++ b/config-model/src/test/derived/music/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "pto"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "mid"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "weight"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "bgnpfrom"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "newestedition"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "year"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "did"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "cbid"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -187,6 +211,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "hiphopvalue_arr"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -208,6 +235,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "metalvalue_arr"
attribute[].datatype STRING
attribute[].collectiontype ARRAY
@@ -229,3 +259,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/newrank/attributes.cfg b/config-model/src/test/derived/newrank/attributes.cfg
index b33c2fbdf9b..f728b1b1d33 100644
--- a/config-model/src/test/derived/newrank/attributes.cfg
+++ b/config-model/src/test/derived/newrank/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "pto"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "mid"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "weight"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "bgnpfrom"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "newestedition"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "year"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "did"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "scorekey"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -187,6 +211,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "cbid"
attribute[].datatype INT32
attribute[].collectiontype SINGLE
@@ -208,3 +235,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/predicate_attribute/attributes.cfg b/config-model/src/test/derived/predicate_attribute/attributes.cfg
index 47e07e2a524..458ee86031d 100644
--- a/config-model/src/test/derived/predicate_attribute/attributes.cfg
+++ b/config-model/src/test/derived/predicate_attribute/attributes.cfg
@@ -19,3 +19,6 @@ attribute[].upperbound 200
attribute[].densepostinglistthreshold 0.2
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/prefixexactattribute/attributes.cfg b/config-model/src/test/derived/prefixexactattribute/attributes.cfg
index d7922a0de69..33fcecb1008 100644
--- a/config-model/src/test/derived/prefixexactattribute/attributes.cfg
+++ b/config-model/src/test/derived/prefixexactattribute/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "attributefield2"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -40,3 +43,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/reference_fields/attributes.cfg b/config-model/src/test/derived/reference_fields/attributes.cfg
index 12dbf896edc..58125f73f9c 100644
--- a/config-model/src/test/derived/reference_fields/attributes.cfg
+++ b/config-model/src/test/derived/reference_fields/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "other_ref"
attribute[].datatype REFERENCE
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "yet_another_ref"
attribute[].datatype REFERENCE
attribute[].collectiontype SINGLE
@@ -61,3 +67,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/sorting/attributes.cfg b/config-model/src/test/derived/sorting/attributes.cfg
index e88dfde03bb..3404d6a0384 100644
--- a/config-model/src/test/derived/sorting/attributes.cfg
+++ b/config-model/src/test/derived/sorting/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "syntaxcheck2"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "infieldonly"
attribute[].datatype STRING
attribute[].collectiontype SINGLE
@@ -61,3 +67,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/tensor/attributes.cfg b/config-model/src/test/derived/tensor/attributes.cfg
index 4634e120a3a..a8531f73c1e 100644
--- a/config-model/src/test/derived/tensor/attributes.cfg
+++ b/config-model/src/test/derived/tensor/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype "tensor<float>(x[2],y[1])"
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "f3"
attribute[].datatype TENSOR
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype "tensor(x{})"
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "f4"
attribute[].datatype TENSOR
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype "tensor(x[10],y[10])"
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "f5"
attribute[].datatype TENSOR
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype "tensor<float>(x[10])"
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "f6"
attribute[].datatype FLOAT
attribute[].collectiontype SINGLE
@@ -103,3 +115,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/derived/types/attributes.cfg b/config-model/src/test/derived/types/attributes.cfg
index e6ffc37e871..290dd5b9a8b 100644
--- a/config-model/src/test/derived/types/attributes.cfg
+++ b/config-model/src/test/derived/types/attributes.cfg
@@ -19,6 +19,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "along"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -40,6 +43,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "abool"
attribute[].datatype BOOL
attribute[].collectiontype SINGLE
@@ -61,6 +67,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "ashortfloat"
attribute[].datatype FLOAT16
attribute[].collectiontype SINGLE
@@ -82,6 +91,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "arrayfield"
attribute[].datatype INT32
attribute[].collectiontype ARRAY
@@ -103,6 +115,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "setfield"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -124,6 +139,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "setfield2"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -145,6 +163,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "setfield3"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -166,6 +187,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "setfield4"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -187,6 +211,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "tagfield"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -208,6 +235,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "juletre"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -229,6 +259,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "album1"
attribute[].datatype STRING
attribute[].collectiontype WEIGHTEDSET
@@ -250,6 +283,9 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
attribute[].name "other"
attribute[].datatype INT64
attribute[].collectiontype SINGLE
@@ -271,3 +307,6 @@ attribute[].upperbound 9223372036854775807
attribute[].densepostinglistthreshold 0.4
attribute[].tensortype ""
attribute[].imported false
+attribute[].index.hnsw.enabled false
+attribute[].index.hnsw.maxlinkspernode 16
+attribute[].index.hnsw.neighborstoexploreatinsert 200
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java
index 3fc05d789f6..e785792839d 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java
@@ -155,4 +155,9 @@ public class ExportingTestCase extends AbstractExportingTestCase {
assertCorrectConfigFiles("tensor2");
}
+ @Test
+ public void testHnswIndex() throws IOException, ParseException {
+ assertCorrectDeriving("hnsw_index");
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorFieldTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorFieldTestCase.java
index b6569357495..b9702c6c4f7 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorFieldTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorFieldTestCase.java
@@ -1,11 +1,16 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchdefinition.processing;
-import com.yahoo.searchdefinition.SearchBuilder;
+import com.yahoo.config.model.test.TestUtil;
import com.yahoo.searchdefinition.parser.ParseException;
import org.junit.Test;
+
+import static com.yahoo.searchdefinition.SearchBuilder.createFromString;
+import static com.yahoo.config.model.test.TestUtil.joinLines;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
@@ -16,7 +21,7 @@ public class TensorFieldTestCase {
@Test
public void requireThatTensorFieldCannotBeOfCollectionType() throws ParseException {
try {
- SearchBuilder.createFromString(getSd("field f1 type array<tensor(x{})> {}"));
+ createFromString(getSd("field f1 type array<tensor(x{})> {}"));
fail("Expected exception");
}
catch (IllegalArgumentException e) {
@@ -28,11 +33,12 @@ public class TensorFieldTestCase {
@Test
public void requireThatTensorFieldCannotBeIndexField() throws ParseException {
try {
- SearchBuilder.createFromString(getSd("field f1 type tensor(x{}) { indexing: index }"));
+ createFromString(getSd("field f1 type tensor(x{}) { indexing: index }"));
fail("Expected exception");
}
catch (IllegalArgumentException e) {
- assertEquals("For search 'test', field 'f1': A field of type 'tensor' cannot be specified as an 'index' field.",
+ assertEquals("For search 'test', field 'f1': A tensor of type 'tensor(x{})' does not support having an 'index'. " +
+ "Currently, only tensors with 1 indexed dimension supports that.",
e.getMessage());
}
}
@@ -40,7 +46,7 @@ public class TensorFieldTestCase {
@Test
public void requireThatTensorAttributeCannotBeFastSearch() throws ParseException {
try {
- SearchBuilder.createFromString(getSd("field f1 type tensor(x{}) { indexing: attribute \n attribute: fast-search }"));
+ createFromString(getSd("field f1 type tensor(x{}) { indexing: attribute \n attribute: fast-search }"));
fail("Expected exception");
}
catch (IllegalArgumentException e) {
@@ -51,7 +57,7 @@ public class TensorFieldTestCase {
@Test
public void requireThatIllegalTensorTypeSpecThrowsException() throws ParseException {
try {
- SearchBuilder.createFromString(getSd("field f1 type tensor(invalid) { indexing: attribute }"));
+ createFromString(getSd("field f1 type tensor(invalid) { indexing: attribute }"));
fail("Expected exception");
}
catch (IllegalArgumentException e) {
@@ -59,8 +65,67 @@ public class TensorFieldTestCase {
}
}
+ @Test
+ public void hnsw_index_is_default_turned_off() throws ParseException {
+ var attr = createFromString(getSd("field t1 type tensor(x[64]) { indexing: attribute }"))
+ .getSearch().getAttribute("t1");
+ assertFalse(attr.hnswIndexParams().isPresent());
+ }
+
+ @Test
+ public void hnsw_index_gets_default_parameters_if_not_specified() throws ParseException {
+ assertHnswIndexParams("", 16, 200);
+ assertHnswIndexParams("index: hnsw", 16, 200);
+ }
+
+ @Test
+ public void hnsw_index_parameters_can_be_specified() throws ParseException {
+ assertHnswIndexParams("index { hnsw { max-links-per-node: 32 } }", 32, 200);
+ assertHnswIndexParams("index { hnsw { neighbors-to-explore-at-insert: 300 } }", 16, 300);
+ assertHnswIndexParams(joinLines("index {",
+ " hnsw {",
+ " max-links-per-node: 32",
+ " neighbors-to-explore-at-insert: 300",
+ " }",
+ "}"),
+ 32, 300);
+ }
+
+ @Test
+ public void tensor_with_hnsw_index_must_be_an_attribute() throws ParseException {
+ try {
+ createFromString(getSd("field t1 type tensor(x[64]) { indexing: index }"));
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertEquals("For search 'test', field 't1': A tensor that has an index must also be an attribute.", e.getMessage());
+ }
+ }
+
private static String getSd(String field) {
- return "search test {\n document test {\n" + field + "}\n}\n";
+ return joinLines("search test {",
+ " document test {",
+ " " + field,
+ " }",
+ "}");
+ }
+
+ private void assertHnswIndexParams(String indexSpec, int maxLinksPerNode, int neighborsToExploreAtInsert) throws ParseException {
+ var sd = getSdWithIndexSpec(indexSpec);
+ System.out.println(sd);
+ var search = createFromString(sd).getSearch();
+ var attr = search.getAttribute("t1");
+ var params = attr.hnswIndexParams();
+ assertTrue(params.isPresent());
+ assertEquals(maxLinksPerNode, params.get().maxLinksPerNode());
+ assertEquals(neighborsToExploreAtInsert, params.get().neighborsToExploreAtInsert());
+ }
+
+ private String getSdWithIndexSpec(String indexSpec) {
+ return getSd(joinLines("field t1 type tensor(x[64]) {",
+ " indexing: attribute | index",
+ " " + indexSpec,
+ "}"));
}
private void assertStartsWith(String prefix, String string) {