From d57fdea60bb4f52e39db000d965673ac87026cc0 Mon Sep 17 00:00:00 2001 From: Vijayan Balasubramanian Date: Tue, 17 Dec 2024 11:42:48 -0800 Subject: [PATCH] Allow validation for non knn index only after 2.17.0 (#2315) * Allow validation for non knn index only after 2.17.0 Before 2.17.0, non knn index are allowed to create knn_vector fields with model id and method params, however this is not allowed from 2.17.0. Hence, to maintain backward compatibility we will not add validation for any indices created before 2.17.0. Signed-off-by: Vijayan Balasubramanian * Add bwc test for model id This is applicable for index created before 2.17 Signed-off-by: Vijayan Balasubramanian --------- Signed-off-by: Vijayan Balasubramanian --- CHANGELOG.md | 1 + qa/restart-upgrade/build.gradle | 29 ++++++++ .../bwc/AbstractRestartUpgradeTestCase.java | 9 ++- .../java/org/opensearch/knn/bwc/ModelIT.java | 33 ++++++++- .../knn/bwc/PainlessScriptScoringIT.java | 71 +++++++++++++++++++ .../opensearch/knn/bwc/ScriptScoringIT.java | 59 ++++++++++++++- .../index/mapper/KNNVectorFieldMapper.java | 9 ++- .../opensearch/knn/index/OpenSearchIT.java | 24 +++++++ .../org/opensearch/knn/KNNRestTestCase.java | 17 +++++ 9 files changed, 243 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6cd767d..3a5fda2a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Optimizes lucene query execution to prevent unnecessary rewrites (#2305)[https://github.com/opensearch-project/k-NN/pull/2305] ### Bug Fixes * Fixing the bug when a segment has no vector field present for disk based vector search (#2282)[https://github.com/opensearch-project/k-NN/pull/2282] +* Allow validation for non knn index only after 2.17.0 (#2315)[https://github.com/opensearch-project/k-NN/pull/2315] ### Infrastructure * Updated C++ version in JNI from c++11 to c++17 [#2259](https://github.com/opensearch-project/k-NN/pull/2259) * Upgrade bytebuddy and objenesis version to match OpenSearch core and, update github ci runner for macos [#2279](https://github.com/opensearch-project/k-NN/pull/2279) diff --git a/qa/restart-upgrade/build.gradle b/qa/restart-upgrade/build.gradle index 3868297bb..3dbf151a7 100644 --- a/qa/restart-upgrade/build.gradle +++ b/qa/restart-upgrade/build.gradle @@ -112,6 +112,20 @@ testClusters { excludeTestsMatching "org.opensearch.knn.bwc.IndexingIT.testKNNIndexLuceneForceMerge" } } + if (!(knn_bwc_version.startsWith("2.13.") || + knn_bwc_version.startsWith("2.14.") || + knn_bwc_version.startsWith("2.15.") || + knn_bwc_version.startsWith("2.16."))) { + filter { + excludeTestsMatching "org.opensearch.knn.bwc.ModelIT.testNonKNNIndex_withModelId" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withFaissEngine" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withNmslibEngine" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withLuceneEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withFaissEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withNmslibEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withLuceneEngine" + } + } nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}".getName()}") @@ -201,6 +215,21 @@ testClusters { } } + if (!(knn_bwc_version.startsWith("2.13.") || + knn_bwc_version.startsWith("2.14.") || + knn_bwc_version.startsWith("2.15.") || + knn_bwc_version.startsWith("2.16."))) { + filter { + excludeTestsMatching "org.opensearch.knn.bwc.ModelIT.testNonKNNIndex_withModelId" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withFaissEngine" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withNmslibEngine" + excludeTestsMatching "org.opensearch.knn.bwc.PainlessScriptScoringIT.testNonKNNIndex_withMethodParams_withLuceneEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withFaissEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withNmslibEngine" + excludeTestsMatching "org.opensearch.knn.bwc.ScriptScoringIT.testNonKNNIndex_withMethodParams_withLuceneEngine" + } + } + nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}".getName()}") systemProperty 'tests.security.manager', 'false' diff --git a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/AbstractRestartUpgradeTestCase.java b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/AbstractRestartUpgradeTestCase.java index 667a39d16..e79e2abef 100644 --- a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/AbstractRestartUpgradeTestCase.java +++ b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/AbstractRestartUpgradeTestCase.java @@ -20,9 +20,12 @@ public abstract class AbstractRestartUpgradeTestCase extends KNNRestTestCase { @Before protected void setIndex() { - // Creating index name by concatenating "knn-bwc-" prefix with test method name - // for all the tests in this sub-project - testIndex = KNN_BWC_PREFIX + getTestName().toLowerCase(Locale.ROOT); + // Creating index name by concatenating "knn-bwc-" prefix with test class name and then with method name + // for all the tests in this sub-project to generate unique index name + testIndex = new StringBuilder().append(KNN_BWC_PREFIX) + .append(getTestClass().getName().toLowerCase(Locale.ROOT)) + .append(getTestName().toLowerCase(Locale.ROOT)) + .toString(); } @Override diff --git a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ModelIT.java b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ModelIT.java index c2bcdbf83..29496cff9 100644 --- a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ModelIT.java +++ b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ModelIT.java @@ -43,6 +43,7 @@ public class ModelIT extends AbstractRestartUpgradeTestCase { private static final String TEST_MODEL_INDEX_DEFAULT = KNN_BWC_PREFIX + "test-model-index-default"; private static final String TRAINING_INDEX = KNN_BWC_PREFIX + "train-index"; private static final String TRAINING_INDEX_DEFAULT = KNN_BWC_PREFIX + "train-index-default"; + private static final String TRAINING_INDEX_FOR_NON_KNN_INDEX = KNN_BWC_PREFIX + "train-index-for-non-knn-index"; private static final String TRAINING_FIELD = "train-field"; private static final String TEST_FIELD = "test-field"; private static final int DIMENSIONS = 5; @@ -50,17 +51,19 @@ public class ModelIT extends AbstractRestartUpgradeTestCase { private static int DOC_ID_TEST_MODEL_INDEX = 0; private static int DOC_ID_TEST_MODEL_INDEX_DEFAULT = 0; private static final int DELAY_MILLI_SEC = 1000; - private static final int EXP_NUM_OF_MODELS = 2; + private static final int MIN_NUM_OF_MODELS = 2; private static final int K = 5; private static final int NUM_DOCS = 10; private static final int NUM_DOCS_TEST_MODEL_INDEX = 100; private static final int NUM_DOCS_TEST_MODEL_INDEX_DEFAULT = 100; + private static final int NUM_DOCS_TEST_MODEL_INDEX_FOR_NON_KNN_INDEX = 100; private static final int NUM_OF_ATTEMPTS = 30; private static int QUERY_COUNT = 0; private static int QUERY_COUNT_TEST_MODEL_INDEX = 0; private static int QUERY_COUNT_TEST_MODEL_INDEX_DEFAULT = 0; private static final String TEST_MODEL_ID = "test-model-id"; private static final String TEST_MODEL_ID_DEFAULT = "test-model-id-default"; + private static final String TEST_MODEL_ID_FOR_NON_KNN_INDEX = "test-model-id-for-non-knn-index"; private static final String MODEL_DESCRIPTION = "Description for train model test"; // KNN model test @@ -135,6 +138,32 @@ public void testKNNModelDefault() throws Exception { } } + public void testNonKNNIndex_withModelId() throws Exception { + if (isRunningAgainstOldCluster()) { + + // Create a training index and randomly ingest data into it + createBasicKnnIndex(TRAINING_INDEX_FOR_NON_KNN_INDEX, TRAINING_FIELD, DIMENSIONS); + bulkIngestRandomVectors(TRAINING_INDEX_FOR_NON_KNN_INDEX, TRAINING_FIELD, NUM_DOCS, DIMENSIONS); + + trainKNNModel(TEST_MODEL_ID_FOR_NON_KNN_INDEX, TRAINING_INDEX_FOR_NON_KNN_INDEX, TRAINING_FIELD, DIMENSIONS, MODEL_DESCRIPTION); + validateModelCreated(TEST_MODEL_ID_FOR_NON_KNN_INDEX); + + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + modelIndexMapping(TEST_FIELD, TEST_MODEL_ID_FOR_NON_KNN_INDEX) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + Thread.sleep(1000); + DOC_ID = NUM_DOCS; + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + deleteKNNIndex(testIndex); + deleteKNNIndex(TRAINING_INDEX_FOR_NON_KNN_INDEX); + deleteKNNModel(TEST_MODEL_ID_FOR_NON_KNN_INDEX); + } + } + // Delete Models and ".opensearch-knn-models" index to clear cluster metadata @AfterClass public static void wipeAllModels() throws IOException { @@ -168,7 +197,7 @@ public void searchKNNModel(String testModelID) throws Exception { XContentParser parser = createParser(MediaTypeRegistry.getDefaultMediaType().xContent(), responseBody); SearchResponse searchResponse = SearchResponse.fromXContent(parser); assertNotNull(searchResponse); - assertEquals(EXP_NUM_OF_MODELS, searchResponse.getHits().getHits().length); + assertTrue(MIN_NUM_OF_MODELS <= searchResponse.getHits().getHits().length); for (SearchHit hit : searchResponse.getHits().getHits()) { assertTrue(hit.getId().startsWith(testModelID)); diff --git a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/PainlessScriptScoringIT.java b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/PainlessScriptScoringIT.java index 084938580..67e1f6d34 100644 --- a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/PainlessScriptScoringIT.java +++ b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/PainlessScriptScoringIT.java @@ -5,6 +5,9 @@ package org.opensearch.knn.bwc; +import org.opensearch.knn.index.SpaceType; +import org.opensearch.knn.index.engine.KNNEngine; + public class PainlessScriptScoringIT extends AbstractRestartUpgradeTestCase { private static final String TEST_FIELD = "test-field"; private static final int DIMENSIONS = 5; @@ -53,4 +56,72 @@ public void testKNNL1PainlessScriptScore() throws Exception { } } + public void testNonKNNIndex_withMethodParams_withFaissEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.FAISS.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + DOC_ID = NUM_DOCS; + QUERY_COUNT = NUM_DOCS; + String source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + forceMergeKnnIndex(testIndex, 1); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + deleteKNNIndex(testIndex); + } + } + + public void testNonKNNIndex_withMethodParams_withNmslibEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.NMSLIB.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + DOC_ID = NUM_DOCS; + QUERY_COUNT = NUM_DOCS; + String source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + forceMergeKnnIndex(testIndex, 1); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + deleteKNNIndex(testIndex); + } + } + + public void testNonKNNIndex_withMethodParams_withLuceneEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.LUCENE.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + DOC_ID = NUM_DOCS; + QUERY_COUNT = NUM_DOCS; + String source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + source = createL1PainlessScriptSource(TEST_FIELD, DIMENSIONS, QUERY_COUNT); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + forceMergeKnnIndex(testIndex, 1); + validateKNNPainlessScriptScoreSearch(testIndex, TEST_FIELD, source, QUERY_COUNT, K); + deleteKNNIndex(testIndex); + } + } } diff --git a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ScriptScoringIT.java b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ScriptScoringIT.java index c4fd05c03..df530776d 100644 --- a/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ScriptScoringIT.java +++ b/qa/restart-upgrade/src/test/java/org/opensearch/knn/bwc/ScriptScoringIT.java @@ -14,6 +14,7 @@ import org.opensearch.knn.KNNResult; import org.opensearch.knn.index.SpaceType; import org.opensearch.core.rest.RestStatus; +import org.opensearch.knn.index.engine.KNNEngine; import java.util.Collections; import java.util.HashMap; @@ -96,6 +97,63 @@ public void testKNNInnerProductScriptScore() throws Exception { } } + public void testNonKNNIndex_withMethodParams_withFaissEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.FAISS.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + QUERY_COUNT = NUM_DOCS; + DOC_ID = NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + deleteKNNIndex(testIndex); + } + } + + public void testNonKNNIndex_withMethodParams_withNmslibEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.NMSLIB.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + QUERY_COUNT = NUM_DOCS; + DOC_ID = NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + deleteKNNIndex(testIndex); + } + } + + public void testNonKNNIndex_withMethodParams_withLuceneEngine() throws Exception { + if (isRunningAgainstOldCluster()) { + createKnnIndex( + testIndex, + createKNNDefaultScriptScoreSettings(), + createKnnIndexMapping(TEST_FIELD, DIMENSIONS, "hnsw", KNNEngine.LUCENE.getName(), SpaceType.DEFAULT.getValue(), false) + ); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + } else { + QUERY_COUNT = NUM_DOCS; + DOC_ID = NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + addKNNDocs(testIndex, TEST_FIELD, DIMENSIONS, DOC_ID, NUM_DOCS); + QUERY_COUNT = QUERY_COUNT + NUM_DOCS; + validateKNNScriptScoreSearch(testIndex, TEST_FIELD, DIMENSIONS, QUERY_COUNT, K, SpaceType.L2); + deleteKNNIndex(testIndex); + } + } + // Validate Script score search for space_type : "inner_product" private void validateKNNInnerProductScriptScoreSearch(String testIndex, String testField, int dimension, int numDocs, int k) throws Exception { @@ -121,5 +179,4 @@ private void validateKNNInnerProductScriptScoreSearch(String testIndex, String t assertEquals(expDocID, actualDocID); } } - } diff --git a/src/main/java/org/opensearch/knn/index/mapper/KNNVectorFieldMapper.java b/src/main/java/org/opensearch/knn/index/mapper/KNNVectorFieldMapper.java index beceadde5..67f3efa5b 100644 --- a/src/main/java/org/opensearch/knn/index/mapper/KNNVectorFieldMapper.java +++ b/src/main/java/org/opensearch/knn/index/mapper/KNNVectorFieldMapper.java @@ -262,7 +262,10 @@ public KNNVectorFieldMapper build(BuilderContext context) { ); } - if (originalParameters.getResolvedKnnMethodContext() == null) { + // return FlatVectorFieldMapper only for indices that are created on or after 2.17.0, for others, use either LuceneFieldMapper + // or + // MethodFieldMapper to maintain backwards compatibility + if (originalParameters.getResolvedKnnMethodContext() == null && context.indexCreatedVersion().onOrAfter(Version.V_2_17_0)) { return FlatVectorFieldMapper.createFieldMapper( buildFullName(context), name, @@ -375,8 +378,8 @@ public Mapper.Builder parse(String name, Map node, ParserCont ); } - // Check for flat configuration - if (isKNNDisabled(parserContext.getSettings())) { + // Check for flat configuration and validate only if index is created after 2.17 + if (isKNNDisabled(parserContext.getSettings()) && parserContext.indexVersionCreated().onOrAfter(Version.V_2_17_0)) { validateFromFlat(builder); } else if (builder.modelId.get() != null) { validateFromModel(builder); diff --git a/src/test/java/org/opensearch/knn/index/OpenSearchIT.java b/src/test/java/org/opensearch/knn/index/OpenSearchIT.java index 7e375f884..9ca041580 100644 --- a/src/test/java/org/opensearch/knn/index/OpenSearchIT.java +++ b/src/test/java/org/opensearch/knn/index/OpenSearchIT.java @@ -814,6 +814,30 @@ public void testKNNIndex_whenBuildVectorDataStructureIsLessThanDocCount_thenBuil deleteKNNIndex(indexName); } + public void testCreateNonKNNIndex_withKNNModelID_throwsException() throws Exception { + Settings settings = Settings.builder().put(createKNNDefaultScriptScoreSettings()).build(); + ResponseException ex = expectThrows( + ResponseException.class, + () -> createKnnIndex(INDEX_NAME, settings, createKnnIndexMapping(FIELD_NAME, "random-model-id")) + ); + String expMessage = "Cannot set modelId or method parameters when index.knn setting is false"; + assertThat(EntityUtils.toString(ex.getResponse().getEntity()), containsString(expMessage)); + } + + public void testCreateNonKNNIndex_withKNNMethodParams_throwsException() throws Exception { + Settings settings = Settings.builder().put(createKNNDefaultScriptScoreSettings()).build(); + ResponseException ex = expectThrows( + ResponseException.class, + () -> createKnnIndex( + INDEX_NAME, + settings, + createKnnIndexMapping(FIELD_NAME, 2, "hnsw", KNNEngine.FAISS.getName(), SpaceType.DEFAULT.getValue(), false) + ) + ); + String expMessage = "Cannot set modelId or method parameters when index.knn setting is false"; + assertThat(EntityUtils.toString(ex.getResponse().getEntity()), containsString(expMessage)); + } + /* For this testcase, we will create index with setting build_vector_data_structure_threshold as -1, then index few documents, perform knn search, then, confirm hits because of exact search though there are no graph. In next step, update setting to 0, force merge segment to 1, perform knn search and confirm expected diff --git a/src/testFixtures/java/org/opensearch/knn/KNNRestTestCase.java b/src/testFixtures/java/org/opensearch/knn/KNNRestTestCase.java index 632543e43..a5b4b0692 100644 --- a/src/testFixtures/java/org/opensearch/knn/KNNRestTestCase.java +++ b/src/testFixtures/java/org/opensearch/knn/KNNRestTestCase.java @@ -83,6 +83,7 @@ import static org.opensearch.knn.common.KNNConstants.METHOD_PARAMETER_NLIST; import static org.opensearch.knn.common.KNNConstants.METHOD_PARAMETER_SPACE_TYPE; import static org.opensearch.knn.common.KNNConstants.MODEL_DESCRIPTION; +import static org.opensearch.knn.common.KNNConstants.MODEL_ID; import static org.opensearch.knn.common.KNNConstants.MODEL_STATE; import static org.opensearch.knn.common.KNNConstants.TRAIN_FIELD_PARAMETER; import static org.opensearch.knn.common.KNNConstants.TRAIN_INDEX_PARAMETER; @@ -382,6 +383,22 @@ protected void putMappingRequest(String index, String mapping) throws IOExceptio assertEquals(request.getEndpoint() + ": failed", RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); } + /** + * Utility to create a Knn Index Mapping for given model id + */ + public String createKnnIndexMapping(String fieldName, String modelId) throws IOException { + return XContentFactory.jsonBuilder() + .startObject() + .startObject(PROPERTIES) + .startObject(fieldName) + .field(VECTOR_TYPE, KNN_VECTOR) + .field(MODEL_ID, modelId) + .endObject() + .endObject() + .endObject() + .toString(); + } + /** * Utility to create a Knn Index Mapping */