From df99d753f0fed1820feec2d9e94ef3b444857ce0 Mon Sep 17 00:00:00 2001 From: Britta Weber Date: Sat, 10 May 2014 18:23:07 +0200 Subject: [PATCH] Check if root mapping is actually valid When a mapping is declared and the type is known from the uri then the type can be skipped in the body (see #4483). However, there was no check if the given keys actually make a valid mapping. closes #5864 --- .../index/mapper/DocumentMapperParser.java | 37 ++++-- .../index/mapper/object/ObjectMapper.java | 108 ++++++++++-------- .../index/mapper/object/RootObjectMapper.java | 33 +++++- .../mapper/all/SimpleAllMapperTests.java | 62 +++++++++- .../all/misplaced_mapping_key_in_root.json | 11 ++ .../mapper/all/misplaced_type_in_root.json | 8 ++ .../mapper/all/mistyped_type_in_root.json | 9 ++ .../all/type_date_detection_mapping.json | 8 ++ .../type_dynamic_date_formats_mapping.json | 8 ++ .../all/type_dynamic_template_mapping.json | 17 +++ .../all/type_numeric_detection_mapping.json | 8 ++ .../percolator/PercolatorTests.java | 2 +- .../routing/SimpleRoutingTests.java | 4 +- .../search/sort/SimpleSortTests.java | 3 - 14 files changed, 245 insertions(+), 73 deletions(-) create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/misplaced_mapping_key_in_root.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/misplaced_type_in_root.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/mistyped_type_in_root.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/type_date_detection_mapping.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_date_formats_mapping.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_template_mapping.json create mode 100644 src/test/java/org/elasticsearch/index/mapper/all/type_numeric_detection_mapping.json diff --git a/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java b/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java index 9661fad667c40..6bf0f589070b8 100644 --- a/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java +++ b/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.Version; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.Nullable; @@ -48,7 +49,9 @@ import org.elasticsearch.index.settings.IndexSettings; import org.elasticsearch.index.similarity.SimilarityLookupService; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import static org.elasticsearch.index.mapper.MapperBuilders.doc; @@ -201,31 +204,38 @@ private DocumentMapper parse(String type, Map mapping, String de Mapper.TypeParser.ParserContext parserContext = parserContext(); + // parse RootObjectMapper DocumentMapper.Builder docBuilder = doc(index.name(), indexSettings, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext)); - - for (Map.Entry entry : mapping.entrySet()) { + Iterator> iterator = mapping.entrySet().iterator(); + // parse DocumentMapper + while(iterator.hasNext()) { + Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); Object fieldNode = entry.getValue(); if ("index_analyzer".equals(fieldName)) { + iterator.remove(); NamedAnalyzer analyzer = analysisService.analyzer(fieldNode.toString()); if (analyzer == null) { throw new MapperParsingException("Analyzer [" + fieldNode.toString() + "] not found for index_analyzer setting on root type [" + type + "]"); } docBuilder.indexAnalyzer(analyzer); } else if ("search_analyzer".equals(fieldName)) { + iterator.remove(); NamedAnalyzer analyzer = analysisService.analyzer(fieldNode.toString()); if (analyzer == null) { throw new MapperParsingException("Analyzer [" + fieldNode.toString() + "] not found for search_analyzer setting on root type [" + type + "]"); } docBuilder.searchAnalyzer(analyzer); } else if ("search_quote_analyzer".equals(fieldName)) { + iterator.remove(); NamedAnalyzer analyzer = analysisService.analyzer(fieldNode.toString()); if (analyzer == null) { throw new MapperParsingException("Analyzer [" + fieldNode.toString() + "] not found for search_analyzer setting on root type [" + type + "]"); } docBuilder.searchQuoteAnalyzer(analyzer); } else if ("analyzer".equals(fieldName)) { + iterator.remove(); NamedAnalyzer analyzer = analysisService.analyzer(fieldNode.toString()); if (analyzer == null) { throw new MapperParsingException("Analyzer [" + fieldNode.toString() + "] not found for analyzer setting on root type [" + type + "]"); @@ -235,11 +245,26 @@ private DocumentMapper parse(String type, Map mapping, String de } else { Mapper.TypeParser typeParser = rootTypeParsers.get(fieldName); if (typeParser != null) { + iterator.remove(); docBuilder.put(typeParser.parse(fieldName, (Map) fieldNode, parserContext)); } } } + ImmutableMap attributes = ImmutableMap.of(); + if (mapping.containsKey("_meta")) { + attributes = ImmutableMap.copyOf((Map) mapping.get("_meta")); + mapping.remove("_meta"); + } + docBuilder.meta(attributes); + + if (!mapping.isEmpty()) { + String remainingFields = ""; + for (String key : mapping.keySet()) { + remainingFields += " [" + key + " : " + mapping.get(key).toString() + "]"; + } + throw new MapperParsingException("Root type mapping not empty after parsing! Remaining fields:" + remainingFields); + } if (!docBuilder.hasIndexAnalyzer()) { docBuilder.indexAnalyzer(analysisService.defaultIndexAnalyzer()); } @@ -250,12 +275,6 @@ private DocumentMapper parse(String type, Map mapping, String de docBuilder.searchAnalyzer(analysisService.defaultSearchQuoteAnalyzer()); } - ImmutableMap attributes = ImmutableMap.of(); - if (mapping.containsKey("_meta")) { - attributes = ImmutableMap.copyOf((Map) mapping.get("_meta")); - } - docBuilder.meta(attributes); - DocumentMapper documentMapper = docBuilder.build(this); // update the source with the generated one documentMapper.refreshSource(); @@ -279,7 +298,6 @@ private Tuple> extractMapping(String type, Map> mapping; if (type == null || type.equals(rootName)) { @@ -287,7 +305,6 @@ private Tuple> extractMapping(String type, Map(type, root); } - return mapping; } } diff --git a/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java b/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java index 1ce367c79e9bb..3daca2fa3bdd5 100644 --- a/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java @@ -180,63 +180,83 @@ protected ObjectMapper createMapper(String name, String fullPath, boolean enable public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - Map objectNode = node; ObjectMapper.Builder builder = createBuilder(name); + Iterator> iterator = node.entrySet().iterator(); + while (iterator.hasNext()) { - boolean nested = false; - boolean nestedIncludeInParent = false; - boolean nestedIncludeInRoot = false; - for (Map.Entry entry : objectNode.entrySet()) { + Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); Object fieldNode = entry.getValue(); + parseObjectOrDocumentTyeProperties( fieldName, fieldNode, parserContext, builder); + parseObjectProperties(name, fieldName, fieldNode, builder); + } + parseNested(name, node, builder); + return builder; + } - if (fieldName.equals("dynamic")) { - String value = fieldNode.toString(); - if (value.equalsIgnoreCase("strict")) { - builder.dynamic(Dynamic.STRICT); - } else { - builder.dynamic(nodeBooleanValue(fieldNode) ? Dynamic.TRUE : Dynamic.FALSE); - } - } else if (fieldName.equals("type")) { - String type = fieldNode.toString(); - if (type.equals(CONTENT_TYPE)) { - builder.nested = Nested.NO; - } else if (type.equals(NESTED_CONTENT_TYPE)) { - nested = true; - } else { - throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]"); - } - } else if (fieldName.equals("include_in_parent")) { - nestedIncludeInParent = nodeBooleanValue(fieldNode); - } else if (fieldName.equals("include_in_root")) { - nestedIncludeInRoot = nodeBooleanValue(fieldNode); - } else if (fieldName.equals("enabled")) { - builder.enabled(nodeBooleanValue(fieldNode)); - } else if (fieldName.equals("path")) { - builder.pathType(parsePathType(name, fieldNode.toString())); - } else if (fieldName.equals("properties")) { - if (fieldNode instanceof Collection && ((Collection) fieldNode).isEmpty()) { - // nothing to do here, empty (to support "properties: []" case) - } else if (!(fieldNode instanceof Map)) { - throw new ElasticsearchParseException("properties must be a map type"); - } else { - parseProperties(builder, (Map) fieldNode, parserContext); - } - } else if (fieldName.equals("include_in_all")) { - builder.includeInAll(nodeBooleanValue(fieldNode)); + protected static boolean parseObjectOrDocumentTyeProperties(String fieldName, Object fieldNode, ParserContext parserContext, ObjectMapper.Builder builder) { + if (fieldName.equals("dynamic")) { + String value = fieldNode.toString(); + if (value.equalsIgnoreCase("strict")) { + builder.dynamic(Dynamic.STRICT); } else { - processField(builder, fieldName, fieldNode); + builder.dynamic(nodeBooleanValue(fieldNode) ? Dynamic.TRUE : Dynamic.FALSE); } + return true; + } else if (fieldName.equals("enabled")) { + builder.enabled(nodeBooleanValue(fieldNode)); + return true; + } else if (fieldName.equals("properties")) { + if (fieldNode instanceof Collection && ((Collection) fieldNode).isEmpty()) { + // nothing to do here, empty (to support "properties: []" case) + } else if (!(fieldNode instanceof Map)) { + throw new ElasticsearchParseException("properties must be a map type"); + } else { + parseProperties(builder, (Map) fieldNode, parserContext); + } + return true; + } + return false; + } + + protected static void parseObjectProperties(String name, String fieldName, Object fieldNode, ObjectMapper.Builder builder) { + if (fieldName.equals("path")) { + builder.pathType(parsePathType(name, fieldNode.toString())); + } else if (fieldName.equals("include_in_all")) { + builder.includeInAll(nodeBooleanValue(fieldNode)); } + } + protected static void parseNested(String name, Map node, ObjectMapper.Builder builder) { + boolean nested = false; + boolean nestedIncludeInParent = false; + boolean nestedIncludeInRoot = false; + Object fieldNode = node.get("type"); + if (fieldNode!=null) { + String type = fieldNode.toString(); + if (type.equals(CONTENT_TYPE)) { + builder.nested = Nested.NO; + } else if (type.equals(NESTED_CONTENT_TYPE)) { + nested = true; + } else { + throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]"); + } + } + fieldNode = node.get("include_in_parent"); + if (fieldNode != null) { + nestedIncludeInParent = nodeBooleanValue(fieldNode); + } + fieldNode = node.get("include_in_root"); + if (fieldNode != null) { + nestedIncludeInRoot = nodeBooleanValue(fieldNode); + } if (nested) { builder.nested = Nested.newNested(nestedIncludeInParent, nestedIncludeInRoot); } - return builder; } - private void parseProperties(ObjectMapper.Builder objBuilder, Map propsNode, ParserContext parserContext) { + protected static void parseProperties(ObjectMapper.Builder objBuilder, Map propsNode, ParserContext parserContext) { for (Map.Entry entry : propsNode.entrySet()) { String propName = entry.getKey(); Map propNode = (Map) entry.getValue(); @@ -270,10 +290,6 @@ private void parseProperties(ObjectMapper.Builder objBuilder, Map node, ParserContext parserContext) throws MapperParsingException { + + ObjectMapper.Builder builder = createBuilder(name); + Iterator> iterator = node.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String fieldName = Strings.toUnderscoreCase(entry.getKey()); + Object fieldNode = entry.getValue(); + if (parseObjectOrDocumentTyeProperties( fieldName, fieldNode, parserContext, builder)) { + iterator.remove(); + } + if (processField(builder,fieldName, fieldNode)) { + iterator.remove(); + } + } + return builder; + } + + protected boolean processField(ObjectMapper.Builder builder, String fieldName, Object fieldNode) { if (fieldName.equals("date_formats") || fieldName.equals("dynamic_date_formats")) { List dateTimeFormatters = newArrayList(); if (fieldNode instanceof List) { @@ -141,6 +159,7 @@ protected void processField(ObjectMapper.Builder builder, String fieldName, Obje } else { ((Builder) builder).dynamicDateTimeFormatter(dateTimeFormatters); } + return true; } else if (fieldName.equals("dynamic_templates")) { // "dynamic_templates" : [ // { @@ -160,11 +179,15 @@ protected void processField(ObjectMapper.Builder builder, String fieldName, Obje Map.Entry entry = tmpl.entrySet().iterator().next(); ((Builder) builder).add(DynamicTemplate.parse(entry.getKey(), (Map) entry.getValue())); } + return true; } else if (fieldName.equals("date_detection")) { ((Builder) builder).dateDetection = nodeBooleanValue(fieldNode); + return true; } else if (fieldName.equals("numeric_detection")) { ((Builder) builder).numericDetection = nodeBooleanValue(fieldNode); + return true; } + return false; } } diff --git a/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java b/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java index 2d82cc3d617f1..30f3b6b6b8d24 100644 --- a/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java @@ -22,7 +22,9 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; +import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.lucene.all.AllEntries; @@ -33,18 +35,15 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.FieldMapper; -import org.elasticsearch.index.mapper.MapperTestUtils; +import org.elasticsearch.index.mapper.*; import org.elasticsearch.index.mapper.ParseContext.Document; +import org.elasticsearch.index.mapper.internal.*; import org.elasticsearch.test.ElasticsearchTestCase; import org.hamcrest.Matchers; import org.junit.Test; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.elasticsearch.common.io.Streams.copyToBytesFromClasspath; import static org.elasticsearch.common.io.Streams.copyToStringFromClasspath; @@ -323,4 +322,55 @@ public void testMultiField_defaults() throws IOException { assertThat(allEntries.fields(), hasSize(1)); assertThat(allEntries.fields(), hasItem("foo.bar")); } + + @Test(expected = MapperParsingException.class) + public void testMisplacedTypeInRoot() throws IOException { + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/misplaced_type_in_root.json"); + DocumentMapper docMapper = MapperTestUtils.newParser().parse("test", mapping); + } + + // unrelated to https://github.com/elasticsearch/elasticsearch/issues/5864 + @Test(expected = MapperParsingException.class) + public void testMistypedTypeInRoot() throws IOException { + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/mistyped_type_in_root.json"); + DocumentMapper docMapper = MapperTestUtils.newParser().parse("test", mapping); + } + + // issue https://github.com/elasticsearch/elasticsearch/issues/5864 + @Test(expected = MapperParsingException.class) + public void testMisplacedMappingAsRoot() throws IOException { + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/misplaced_mapping_key_in_root.json"); + DocumentMapper docMapper = MapperTestUtils.newParser().parse("test", mapping); + } + + // issue https://github.com/elasticsearch/elasticsearch/issues/5864 + // test that RootObjectMapping still works + @Test + public void testRootObjectMapperPropertiesDoNotCauseException() throws IOException { + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/type_dynamic_template_mapping.json"); + MapperTestUtils.newParser().parse("test", mapping); + mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/type_dynamic_date_formats_mapping.json"); + MapperTestUtils.newParser().parse("test", mapping); + mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/type_date_detection_mapping.json"); + MapperTestUtils.newParser().parse("test", mapping); + mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/all/type_numeric_detection_mapping.json"); + MapperTestUtils.newParser().parse("test", mapping); + } + + // issue https://github.com/elasticsearch/elasticsearch/issues/5864 + @Test + public void testRootMappersStillWorking() { + String mapping = "{"; + Map rootTypes = new HashMap<>(); + //just pick some example from DocumentMapperParser.rootTypeParsers + rootTypes.put(SizeFieldMapper.NAME, "{\"enabled\" : true}"); + rootTypes.put(IndexFieldMapper.NAME, "{\"enabled\" : true}"); + rootTypes.put(SourceFieldMapper.NAME, "{\"enabled\" : true}"); + rootTypes.put(TypeFieldMapper.NAME, "{\"store\" : true}"); + for (String key : rootTypes.keySet()) { + mapping += "\"" + key+ "\"" + ":" + rootTypes.get(key) + ",\n"; + } + mapping += "\"properties\":{}}" ; + MapperTestUtils.newParser().parse("test", mapping); + } } diff --git a/src/test/java/org/elasticsearch/index/mapper/all/misplaced_mapping_key_in_root.json b/src/test/java/org/elasticsearch/index/mapper/all/misplaced_mapping_key_in_root.json new file mode 100644 index 0000000000000..f08757a9e9db0 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/misplaced_mapping_key_in_root.json @@ -0,0 +1,11 @@ +{ + "mapping": { + "test": { + "properties": { + "foo": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/misplaced_type_in_root.json b/src/test/java/org/elasticsearch/index/mapper/all/misplaced_type_in_root.json new file mode 100644 index 0000000000000..f4b325c6c1aaa --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/misplaced_type_in_root.json @@ -0,0 +1,8 @@ +{ + "type": "string", + "properties": { + "foo": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/mistyped_type_in_root.json b/src/test/java/org/elasticsearch/index/mapper/all/mistyped_type_in_root.json new file mode 100644 index 0000000000000..19edf59767047 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/mistyped_type_in_root.json @@ -0,0 +1,9 @@ +{ + "testX": { + "properties": { + "foo": { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/type_date_detection_mapping.json b/src/test/java/org/elasticsearch/index/mapper/all/type_date_detection_mapping.json new file mode 100644 index 0000000000000..c2db712ced5e5 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/type_date_detection_mapping.json @@ -0,0 +1,8 @@ +{ + "date_detection" : false, + "properties": { + "foo": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_date_formats_mapping.json b/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_date_formats_mapping.json new file mode 100644 index 0000000000000..7e6afd397c488 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_date_formats_mapping.json @@ -0,0 +1,8 @@ +{ + "dynamic_date_formats" : ["yyyy-MM-dd", "dd-MM-yyyy"], + "properties": { + "foo": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_template_mapping.json b/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_template_mapping.json new file mode 100644 index 0000000000000..b155fb7204be0 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/type_dynamic_template_mapping.json @@ -0,0 +1,17 @@ +{ + "dynamic_templates" : [ + { + "dynamic_template_name" : { + "match" : "*", + "mapping" : { + "store" : true + } + } + } + ], + "properties": { + "foo": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/mapper/all/type_numeric_detection_mapping.json b/src/test/java/org/elasticsearch/index/mapper/all/type_numeric_detection_mapping.json new file mode 100644 index 0000000000000..4729354600706 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/all/type_numeric_detection_mapping.json @@ -0,0 +1,8 @@ +{ + "numeric_detection" : false, + "properties": { + "foo": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/percolator/PercolatorTests.java b/src/test/java/org/elasticsearch/percolator/PercolatorTests.java index 38ea797f21891..59b7724910886 100644 --- a/src/test/java/org/elasticsearch/percolator/PercolatorTests.java +++ b/src/test/java/org/elasticsearch/percolator/PercolatorTests.java @@ -1684,7 +1684,7 @@ public void testPercolationWithDynamicTemplates() throws Exception { .field("incude_in_all", false) .endObject() .endObject() - .startArray("dynamic_template") + .startArray("dynamic_templates") .startObject() .startObject("custom_fields") .field("path_match", "custom.*") diff --git a/src/test/java/org/elasticsearch/routing/SimpleRoutingTests.java b/src/test/java/org/elasticsearch/routing/SimpleRoutingTests.java index 2e97ed34275b1..ac870e27a6357 100644 --- a/src/test/java/org/elasticsearch/routing/SimpleRoutingTests.java +++ b/src/test/java/org/elasticsearch/routing/SimpleRoutingTests.java @@ -234,8 +234,8 @@ public void testRequiredRoutingMapping() throws Exception { public void testRequiredRoutingWithPathMapping() throws Exception { client().admin().indices().prepareCreate("test") .addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("_routing").field("required", true).field("path", "routing_field").endObject() - .startObject("routing_field").field("type", "string").field("index", randomBoolean() ? "no" : "not_analyzed").field("doc_values", randomBoolean() ? "yes" : "no").endObject() + .startObject("_routing").field("required", true).field("path", "routing_field").endObject().startObject("properties") + .startObject("routing_field").field("type", "string").field("index", randomBoolean() ? "no" : "not_analyzed").field("doc_values", randomBoolean() ? "yes" : "no").endObject().endObject() .endObject().endObject()) .execute().actionGet(); ensureGreen(); diff --git a/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java b/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java index 05ddf6fe31017..6090ce09c896e 100644 --- a/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java +++ b/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java @@ -848,9 +848,6 @@ public void testSortMissingNumbers() throws Exception { .startObject("fielddata").field("format", maybeDocValues() ? "doc_values" : null).endObject() .endObject() .endObject() - .startObject("d_value") - .field("type", "float") - .endObject() .endObject() .endObject())); ensureGreen();