Browse Source

Search as you type field to support subfields (#82430)

It has been reported that the search as you type field accepts sub-fields as part of its mapping definition, but those are being silently ignored. With this commit we add support for multi-fields to the search as you type field.

Closes #56326
Luca Cavanna 3 years ago
parent
commit
f4af39534e

+ 12 - 2
modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/extras/SearchAsYouTypeFieldMapper.java

@@ -255,7 +255,16 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
             }
             }
             ft.setPrefixField(prefixFieldType);
             ft.setPrefixField(prefixFieldType);
             ft.setShingleFields(shingleFieldTypes);
             ft.setShingleFields(shingleFieldTypes);
-            return new SearchAsYouTypeFieldMapper(name, ft, copyTo.build(), indexAnalyzers, prefixFieldMapper, shingleFieldMappers, this);
+            return new SearchAsYouTypeFieldMapper(
+                name,
+                ft,
+                copyTo.build(),
+                indexAnalyzers,
+                prefixFieldMapper,
+                shingleFieldMappers,
+                multiFieldsBuilder.build(this, context),
+                this
+            );
         }
         }
     }
     }
 
 
@@ -644,9 +653,10 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
         Map<String, NamedAnalyzer> indexAnalyzers,
         Map<String, NamedAnalyzer> indexAnalyzers,
         PrefixFieldMapper prefixField,
         PrefixFieldMapper prefixField,
         ShingleFieldMapper[] shingleFields,
         ShingleFieldMapper[] shingleFields,
+        MultiFields multiFields,
         Builder builder
         Builder builder
     ) {
     ) {
-        super(simpleName, mappedFieldType, indexAnalyzers, MultiFields.empty(), copyTo, false, null);
+        super(simpleName, mappedFieldType, indexAnalyzers, multiFields, copyTo, false, null);
         this.prefixField = prefixField;
         this.prefixField = prefixField;
         this.shingleFields = shingleFields;
         this.shingleFields = shingleFields;
         this.maxShingleSize = builder.maxShingleSize.getValue();
         this.maxShingleSize = builder.maxShingleSize.getValue();

+ 32 - 15
modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/extras/SearchAsYouTypeFieldMapperTests.java

@@ -249,28 +249,42 @@ public class SearchAsYouTypeFieldMapperTests extends MapperTestCase {
 
 
     public void testMultiFields() throws IOException {
     public void testMultiFields() throws IOException {
         for (int shingleSize = 2; shingleSize < 4; shingleSize++) {
         for (int shingleSize = 2; shingleSize < 4; shingleSize++) {
-            assertMultiField(shingleSize);
+            int size = shingleSize;
+            MapperService mapperService = createMapperService(fieldMapping(b -> {
+                b.field("type", "text");
+                b.startObject("fields");
+                {
+                    b.startObject("suggest").field("type", "search_as_you_type").field("max_shingle_size", size).endObject();
+                }
+                b.endObject();
+            }));
+            assertMultiField(shingleSize, mapperService, "field.suggest", "field");
+        }
+        for (int shingleSize = 2; shingleSize < 4; shingleSize++) {
+            String path = "field";
+            int size = shingleSize;
+            MapperService mapperService = createMapperService(fieldMapping(b -> {
+                b.field("type", "search_as_you_type").field("max_shingle_size", size);
+                b.startObject("fields");
+                {
+                    b.startObject("text").field("type", "text").endObject();
+                }
+                b.endObject();
+            }));
+            assertMultiField(shingleSize, mapperService, "field", "field.text");
         }
         }
     }
     }
 
 
-    private void assertMultiField(int shingleSize) throws IOException {
-        String path = "field.suggest";
+    private void assertMultiField(int shingleSize, MapperService mapperService, String suggestPath, String textPath) throws IOException {
         List<String> fields = new ArrayList<>();
         List<String> fields = new ArrayList<>();
-        fields.add(path);
-        MapperService mapperService = createMapperService(fieldMapping(b -> {
-            b.field("type", "text");
-            b.startObject("fields");
-            {
-                b.startObject("suggest").field("type", "search_as_you_type").field("max_shingle_size", shingleSize).endObject();
-            }
-            b.endObject();
-        }));
-        MappedFieldType fieldType = mapperService.fieldType(path + "._index_prefix");
+        fields.add(suggestPath);
+        fields.add(textPath);
+        MappedFieldType fieldType = mapperService.fieldType(suggestPath + "._index_prefix");
         assertThat(fieldType, instanceOf(PrefixFieldType.class));
         assertThat(fieldType, instanceOf(PrefixFieldType.class));
         PrefixFieldType prefixFieldType = (PrefixFieldType) fieldType;
         PrefixFieldType prefixFieldType = (PrefixFieldType) fieldType;
-        assertEquals(path, prefixFieldType.parentField);
+        assertEquals(suggestPath, prefixFieldType.parentField);
         for (int i = 2; i < shingleSize; i++) {
         for (int i = 2; i < shingleSize; i++) {
-            String name = path + "._" + i + "gram";
+            String name = suggestPath + "._" + i + "gram";
             fields.add(name);
             fields.add(name);
             fieldType = mapperService.fieldType(name);
             fieldType = mapperService.fieldType(name);
             assertThat(fieldType, instanceOf(ShingleFieldType.class));
             assertThat(fieldType, instanceOf(ShingleFieldType.class));
@@ -279,6 +293,9 @@ public class SearchAsYouTypeFieldMapperTests extends MapperTestCase {
             assertSame(prefixFieldType, ft.prefixFieldType);
             assertSame(prefixFieldType, ft.prefixFieldType);
         }
         }
 
 
+        MappedFieldType textFieldType = mapperService.fieldType(textPath);
+        assertThat(textFieldType, instanceOf(TextFieldMapper.TextFieldType.class));
+
         ParsedDocument doc = mapperService.documentMapper().parse(source(b -> b.field("field", "new york city")));
         ParsedDocument doc = mapperService.documentMapper().parse(source(b -> b.field("field", "new york city")));
         for (String field : fields) {
         for (String field : fields) {
             IndexableField[] indexFields = doc.rootDoc().getFields(field);
             IndexableField[] indexFields = doc.rootDoc().getFields(field);