From 30ddc200f3d14ad9c7a1ac9684f7d0bca185ebd2 Mon Sep 17 00:00:00 2001 From: Junqiu Lei Date: Tue, 21 Nov 2023 14:17:48 -0800 Subject: [PATCH] Fixed field value from nested mapping when train model Signed-off-by: Junqiu Lei --- CHANGELOG.md | 1 + .../org/opensearch/knn/index/IndexUtil.java | 27 ++++++++++++++++++- .../opensearch/knn/index/IndexUtilTests.java | 24 +++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1350e532f..465d37121a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Enhancements ### Bug Fixes * Fix use-after-free case on nmslib search path [#1305](https://github.com/opensearch-project/k-NN/pull/1305) +* Fixed field value from nested mapping when train model [#1318](https://github.com/opensearch-project/k-NN/pull/1318) ### Infrastructure * Upgrade gradle to 8.4 [1289](https://github.com/opensearch-project/k-NN/pull/1289) ### Documentation diff --git a/src/main/java/org/opensearch/knn/index/IndexUtil.java b/src/main/java/org/opensearch/knn/index/IndexUtil.java index 574e4a9773..ffded7626f 100644 --- a/src/main/java/org/opensearch/knn/index/IndexUtil.java +++ b/src/main/java/org/opensearch/knn/index/IndexUtil.java @@ -59,6 +59,31 @@ public static int getFileSizeInKB(String filePath) { return Math.toIntExact((file.length() / BYTES_PER_KILOBYTES) + 1L); // Add one so that integer division rounds up } + /** + * Retrieves a field mapping from properties map by recursively searching through the map. + * + * @param properties A map representing properties, where each key is a property name and + * the value is either a sub-map of properties or the property value itself. + * @param field The name of the field to retrieve. + * @return The value of the field if found, or null if the field is not present in the map. + */ + public static Object getFieldMapping(Map properties, String field) { + if (properties.containsKey(field)) { + return properties.get(field); + } else { + for (Map.Entry entry : properties.entrySet()) { + Object value = entry.getValue(); + if (value instanceof Map) { + Object result = getFieldMapping((Map) value, field); + if (result != null) { + return result; + } + } + } + } + return null; + } + /** * Validate that a field is a k-NN vector field and has the expected dimension * @@ -100,7 +125,7 @@ public static ValidationException validateKnnField( return exception; } - Object fieldMapping = properties.get(field); + Object fieldMapping = getFieldMapping(properties, field); // Check field existence if (fieldMapping == null) { diff --git a/src/test/java/org/opensearch/knn/index/IndexUtilTests.java b/src/test/java/org/opensearch/knn/index/IndexUtilTests.java index 7013ef261a..938376cefd 100644 --- a/src/test/java/org/opensearch/knn/index/IndexUtilTests.java +++ b/src/test/java/org/opensearch/knn/index/IndexUtilTests.java @@ -20,6 +20,8 @@ import org.opensearch.knn.KNNTestCase; import org.opensearch.knn.index.util.KNNEngine; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import static org.mockito.ArgumentMatchers.anyString; @@ -67,4 +69,26 @@ public void testGetLoadParameters() { assertEquals(spaceType2.getValue(), loadParameters.get(SPACE_TYPE)); assertEquals(efSearchValue, loadParameters.get(HNSW_ALGO_EF_SEARCH)); } + + public void testGetFieldMappingNonNestedField() { + Map properties = new HashMap<>(); + properties.put("top_level_field", "top_level_value"); + + Object result = IndexUtil.getFieldMapping(properties, "top_level_field"); + assertEquals("top_level_value", result); + } + + public void testGetFieldMappingNestedField() { + Map deepNestedProperties = new HashMap<>(); + deepNestedProperties.put("deep_inner_field", "deep_value"); + + Map nestedProperties = new HashMap<>(); + nestedProperties.put("nested", Collections.singletonMap("properties", deepNestedProperties)); + + Map properties = new HashMap<>(); + properties.put("top", Collections.singletonMap("properties", nestedProperties)); + + Object deepResult = IndexUtil.getFieldMapping(properties, "deep_inner_field"); + assertEquals("deep_value", deepResult); + } }