Skip to content

Commit

Permalink
Remove support for chained multi-fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
jtibshirani committed May 22, 2019
1 parent 5785941 commit 5a78589
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 108 deletions.
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

0 comments on commit 5a78589

Please sign in to comment.