Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for chained multi-fields. #42333

Merged
merged 4 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/reference/migration/migrate_8_0/mappings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@

The number of completion contexts within a single completion field
has been limited to 10.

[float]
==== Defining multi-fields within multi-fields

Previously, it was possible to define a multi-field within a multi-field.
Defining chained multi-fields was deprecated in 7.3 and is now no longer
supported. To migrate the mappings, all instances of `fields` that occur within
a `fields` block should be removed, either by flattening the chained `fields`
blocks into a single level, or by switching to `copy_to` if appropriate.
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,8 @@ public static boolean parseMultiField(FieldMapper.Builder builder, String name,
String propName, Object propNode) {
if (propName.equals("fields")) {
if (parserContext.isWithinMultiField()) {
deprecationLogger.deprecatedAndMaybeLog("multifield_within_multifield", "At least one multi-field, [" + name + "], was " +
"encountered that itself contains a multi-field. Defining multi-fields within a multi-field is deprecated and will " +
"no longer be supported in 8.0. To resolve the issue, all instances of [fields] that occur within a [fields] block " +
"should be removed from the mappings, either by flattening the chained [fields] blocks into a single level, or " +
"switching to [copy_to] if appropriate.");
throw new IllegalArgumentException("Encountered a multi-field [" + name + "] which itself contains a multi-field. " +
"Defining chained multi-fields is not supported.");
}

parserContext = parserContext.createMultiFieldContext(parserContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper;

import org.apache.lucene.index.IndexableField;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Strings;
Expand Down Expand Up @@ -132,12 +131,6 @@ public void testExternalValuesWithMultifield() throws Exception {
.startObject("field")
.field("type", "text")
.field("store", true)
.startObject("fields")
.startObject("raw")
.field("type", "keyword")
.field("store", true)
.endObject()
.endObject()
.endObject()
.endObject()
.endObject()
Expand All @@ -164,87 +157,5 @@ public void testExternalValuesWithMultifield() throws Exception {
IndexableField field = doc.rootDoc().getField("field.field");
assertThat(field, notNullValue());
assertThat(field.stringValue(), is("foo"));

IndexableField raw = doc.rootDoc().getField("field.field.raw");

assertThat(raw, notNullValue());
assertThat(raw.binaryValue(), is(new BytesRef("foo")));

assertWarnings("At least one multi-field, [field], was " +
"encountered that itself contains a multi-field. Defining multi-fields within a multi-field is deprecated and will " +
"no longer be supported in 8.0. To resolve the issue, all instances of [fields] that occur within a [fields] block " +
"should be removed from the mappings, either by flattening the chained [fields] blocks into a single level, or " +
"switching to [copy_to] if appropriate.");
}

public void testExternalValuesWithMultifieldTwoLevels() throws Exception {
IndexService indexService = createIndex("test");
Map<String, Mapper.TypeParser> mapperParsers = new HashMap<>();
mapperParsers.put(ExternalMapperPlugin.EXTERNAL, new ExternalMapper.TypeParser(ExternalMapperPlugin.EXTERNAL, "foo"));
mapperParsers.put(ExternalMapperPlugin.EXTERNAL_BIS, new ExternalMapper.TypeParser(ExternalMapperPlugin.EXTERNAL, "bar"));
mapperParsers.put(TextFieldMapper.CONTENT_TYPE, new TextFieldMapper.TypeParser());
MapperRegistry mapperRegistry = new MapperRegistry(mapperParsers, Collections.emptyMap(), MapperPlugin.NOOP_FIELD_FILTER);

Supplier<QueryShardContext> queryShardContext = () -> {
return indexService.newQueryShardContext(0, null, () -> { throw new UnsupportedOperationException(); }, null);
};
DocumentMapperParser parser = new DocumentMapperParser(indexService.getIndexSettings(), indexService.mapperService(),
indexService.xContentRegistry(), indexService.similarityService(), mapperRegistry, queryShardContext);

DocumentMapper documentMapper = parser.parse("type", new CompressedXContent(
Strings
.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties")
.startObject("field")
.field("type", ExternalMapperPlugin.EXTERNAL)
.startObject("fields")
.startObject("field")
.field("type", "text")
.startObject("fields")
.startObject("generated")
.field("type", ExternalMapperPlugin.EXTERNAL_BIS)
.endObject()
.startObject("raw")
.field("type", "text")
.endObject()
.endObject()
.endObject()
.startObject("raw")
.field("type", "text")
.endObject()
.endObject()
.endObject()
.endObject().endObject().endObject())));

ParsedDocument doc = documentMapper.parse(new SourceToParse("test", "type", "1", BytesReference
.bytes(XContentFactory.jsonBuilder()
.startObject()
.field("field", "1234")
.endObject()),
XContentType.JSON));

assertThat(doc.rootDoc().getField("field.bool"), notNullValue());
assertThat(doc.rootDoc().getField("field.bool").stringValue(), is("T"));

assertThat(doc.rootDoc().getField("field.point"), notNullValue());

assertThat(doc.rootDoc().getField("field.shape"), notNullValue());

assertThat(doc.rootDoc().getField("field.field"), notNullValue());
assertThat(doc.rootDoc().getField("field.field").stringValue(), is("foo"));

assertThat(doc.rootDoc().getField("field.field.generated.generated"), notNullValue());
assertThat(doc.rootDoc().getField("field.field.generated.generated").stringValue(), is("bar"));

assertThat(doc.rootDoc().getField("field.field.raw"), notNullValue());
assertThat(doc.rootDoc().getField("field.field.raw").stringValue(), is("foo"));

assertThat(doc.rootDoc().getField("field.raw"), notNullValue());
assertThat(doc.rootDoc().getField("field.raw").stringValue(), is("foo"));

assertWarnings("At least one multi-field, [field], was " +
"encountered that itself contains a multi-field. Defining multi-fields within a multi-field is deprecated and will " +
"no longer be supported in 8.0. To resolve the issue, all instances of [fields] that occur within a [fields] block " +
"should be removed from the mappings, either by flattening the chained [fields] blocks into a single level, or " +
"switching to [copy_to] if appropriate.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,8 @@ public void testExternalValuesWithMultifield() throws Exception {
.field("type", ExternalMapperPlugin.EXTERNAL_UPPER)
.startObject("fields")
.startObject("g")
.field("type", "text")
.field("type", "keyword")
.field("store", true)
.startObject("fields")
.startObject("raw")
.field("type", "keyword")
.field("store", true)
.endObject()
.endObject()
.endObject()
.endObject()
.endObject()
Expand All @@ -156,7 +150,7 @@ public void testExternalValuesWithMultifield() throws Exception {
refresh();

SearchResponse response = client().prepareSearch("test-idx")
.setQuery(QueryBuilders.termQuery("f.g.raw", "FOO BAR"))
.setQuery(QueryBuilders.termQuery("f.g", "FOO BAR"))
.execute().actionGet();

assertThat(response.getHits().getTotalHits().value, equalTo((long) 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import static org.elasticsearch.index.analysis.AnalysisRegistry.DEFAULT_ANALYZER_NAME;
import static org.elasticsearch.index.analysis.AnalysisRegistry.DEFAULT_SEARCH_ANALYZER_NAME;
import static org.elasticsearch.index.analysis.AnalysisRegistry.DEFAULT_SEARCH_QUOTED_ANALYZER_NAME;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -186,12 +187,10 @@ public void testMultiFieldWithinMultiField() throws IOException {
Mapper.TypeParser.ParserContext parserContext = new Mapper.TypeParser.ParserContext("type",
null, null, type -> typeParser, Version.CURRENT, null);

TypeParsers.parseField(builder, "some-field", fieldNode, parserContext);
assertWarnings("At least one multi-field, [sub-field], was " +
"encountered that itself contains a multi-field. Defining multi-fields within a multi-field is deprecated and will " +
"no longer be supported in 8.0. To resolve the issue, all instances of [fields] that occur within a [fields] block " +
"should be removed from the mappings, either by flattening the chained [fields] blocks into a single level, or " +
"switching to [copy_to] if appropriate.");
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> TypeParsers.parseField(builder, "some-field", fieldNode, parserContext));
assertThat(e.getMessage(), equalTo("Encountered a multi-field [sub-field] which itself contains a " +
"multi-field. Defining chained multi-fields is not supported."));
}

private Analyzer createAnalyzerWithMode(String name, AnalysisMode mode) {
Expand Down