From 67820f9da1929fde373fa4f0b59fb4d998fc5d84 Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Fri, 26 Apr 2019 10:18:48 +0200 Subject: [PATCH] Fix search_as_you_type's sub-fields to pick their names from the full path of the root field (#41541) The subfields of the search_as_you_type are prefixed with the name of their root field. However they should used the full path of the root field rather than just the name since these fields can appear in a multi-`fields` definition or under an object field. Since this field type is not released yet, this should be considered as a non-issue. --- .../mapper/SearchAsYouTypeFieldMapper.java | 7 +-- .../SearchAsYouTypeFieldMapperTests.java | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapper.java b/modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapper.java index 867e975e9f51c..9a5c389dd8e79 100644 --- a/modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapper.java +++ b/modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapper.java @@ -160,8 +160,9 @@ public SearchAsYouTypeFieldMapper build(Mapper.BuilderContext context) { final NamedAnalyzer searchQuoteAnalyzer = fieldType().searchQuoteAnalyzer(); // set up the prefix field - final String prefixFieldName = name() + PREFIX_FIELD_SUFFIX; - final PrefixFieldType prefixFieldType = new PrefixFieldType(name(), prefixFieldName, Defaults.MIN_GRAM, Defaults.MAX_GRAM); + final String fullName = buildFullName(context); + final String prefixFieldName = fullName + PREFIX_FIELD_SUFFIX; + final PrefixFieldType prefixFieldType = new PrefixFieldType(fullName, prefixFieldName, Defaults.MIN_GRAM, Defaults.MAX_GRAM); prefixFieldType.setIndexOptions(fieldType().indexOptions()); // wrap the root field's index analyzer with shingles and edge ngrams final SearchAsYouTypeAnalyzer prefixIndexWrapper = @@ -180,7 +181,7 @@ public SearchAsYouTypeFieldMapper build(Mapper.BuilderContext context) { for (int i = 0; i < shingleFieldMappers.length; i++) { final int shingleSize = i + 2; final ShingleFieldType shingleFieldType = new ShingleFieldType(fieldType(), shingleSize); - shingleFieldType.setName(getShingleFieldName(name(), shingleSize)); + shingleFieldType.setName(getShingleFieldName(buildFullName(context), shingleSize)); // wrap the root field's index, search, and search quote analyzers with shingles final SearchAsYouTypeAnalyzer shingleIndexWrapper = SearchAsYouTypeAnalyzer.withShingle(indexAnalyzer.analyzer(), shingleSize); diff --git a/modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapperTests.java b/modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapperTests.java index 4622b34ea1514..40bd6d436c148 100644 --- a/modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapperTests.java +++ b/modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapperTests.java @@ -235,6 +235,60 @@ public void testSimpleMerge() throws IOException { } } + public void testMultiFields() throws IOException { + for (int shingleSize = 2; shingleSize < 4; shingleSize++) { + final XContentBuilder mapping = XContentFactory.jsonBuilder() + .startObject() + .startObject("properties") + .startObject("a_field") + .field("type", "text") + .startObject("fields") + .startObject("suggest") + .field("type", "search_as_you_type") + .field("max_shingle_size", shingleSize) + .endObject() + .endObject() + .endObject() + .endObject() + .endObject(); + + final String index = "foo_" + shingleSize; + final String path = "a_field.suggest"; + List fields = new ArrayList<>(); + fields.add(path); + final MapperService mapperService = + createIndex(index, Settings.EMPTY, "_doc", mapping).mapperService(); + FieldType fieldType = mapperService.fullName(path + "._index_prefix"); + assertThat(fieldType, instanceOf(PrefixFieldType.class)); + PrefixFieldType prefixFieldType = (PrefixFieldType) fieldType; + assertEquals(path, prefixFieldType.parentField); + for (int i = 2; i < shingleSize; i++) { + String name = path + "._" + i + "gram"; + fields.add(name); + fieldType = mapperService.fullName(name); + assertThat(fieldType, instanceOf(ShingleFieldType.class)); + ShingleFieldType ft = (ShingleFieldType) fieldType; + assertEquals(i, ft.shingleSize); + assertTrue(prefixFieldType == ft.prefixFieldType); + } + + ParsedDocument doc = mapperService.documentMapper() + .parse(new SourceToParse("test", "_doc", "1", + BytesReference.bytes( + XContentFactory.jsonBuilder() + .startObject() + .field("a_field", "new york city") + .endObject() + ), XContentType.JSON) + ); + for (String field : fields) { + IndexableField[] indexFields = doc.rootDoc().getFields(field); + assertEquals(1, indexFields.length); + assertEquals("new york city", indexFields[0].stringValue()); + } + } + } + public void testIndexOptions() throws IOException { final String mapping = Strings.toString(XContentFactory.jsonBuilder() .startObject()