From 8f73e1e883e0da94359d8d581603d1608fbb38b9 Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Thu, 18 Apr 2019 22:48:22 +0200 Subject: [PATCH] Fix unmapped field handling in the composite aggregation (#41280) The `composite` aggregation maps unknown fields as numerics, this means that any `after` value that is set on a query with an unmapped field on some indices will fail if the provided value is not numeric. This commit changes the default value source to use keyword instead in order to be able to parse any type of after values. --- .../test/search.aggregation/230_composite.yml | 105 +++++++++++++++++- .../composite/TermsValuesSourceBuilder.java | 4 +- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/230_composite.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/230_composite.yml index 8532b40fbc1..bbd8cef689d 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/230_composite.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/230_composite.yml @@ -18,6 +18,22 @@ setup: nested_long: type: long + - do: + indices.create: + index: other + body: + mappings: + properties: + date: + type: date + long: + type: long + nested: + type: nested + properties: + nested_long: + type: long + - do: index: index: test @@ -54,9 +70,15 @@ setup: id: 6 body: { "date": "2017-10-21T07:00:00" } + - do: + index: + index: other + id: 0 + body: { "date": "2017-10-20T03:08:45" } + - do: indices.refresh: - index: [test] + index: [test, other] --- "Simple Composite aggregation": @@ -419,3 +441,84 @@ setup: - match: { aggregations.1.2.buckets.0.doc_count: 2 } - match: { aggregations.1.2.buckets.1.key.nested: 1000 } - match: { aggregations.1.2.buckets.1.doc_count: 1 } + +--- +"Composite aggregation with unmapped field": + - skip: + version: " - 7.0.99" + reason: starting in 7.1 the composite aggregation handles unmapped fields as keywords + + - do: + search: + rest_total_hits_as_int: true + index: [test, other] + body: + aggregations: + test: + composite: + sources: [ + { + "long": { + "terms": { + "field": "long" + } + } + }, + { + "kw": { + "terms": { + "field": "keyword" + } + } + } + ] + + - match: {hits.total: 7} + - length: { aggregations.test.buckets: 5 } + - match: { aggregations.test.buckets.0.key.long: 0} + - match: { aggregations.test.buckets.0.key.kw: "bar" } + - match: { aggregations.test.buckets.0.doc_count: 2 } + - match: { aggregations.test.buckets.1.key.long: 10 } + - match: { aggregations.test.buckets.1.key.kw: "foo"} + - match: { aggregations.test.buckets.1.doc_count: 1 } + - match: { aggregations.test.buckets.2.key.long: 20 } + - match: { aggregations.test.buckets.2.key.kw: "foo" } + - match: { aggregations.test.buckets.2.doc_count: 1 } + - match: { aggregations.test.buckets.3.key.long: 100} + - match: { aggregations.test.buckets.3.key.kw: "bar" } + - match: { aggregations.test.buckets.3.doc_count: 1 } + - match: { aggregations.test.buckets.4.key.long: 1000 } + - match: { aggregations.test.buckets.4.key.kw: "bar" } + - match: { aggregations.test.buckets.4.doc_count: 1 } + + - do: + search: + rest_total_hits_as_int: true + index: [test, other] + body: + aggregations: + test: + composite: + after: { "long": 100, "kw": "bar" } + sources: [ + { + "long": { + "terms": { + "field": "long" + } + } + }, + { + "kw": { + "terms": { + "field": "keyword" + } + } + } + ] + + - match: {hits.total: 7} + - length: { aggregations.test.buckets: 1 } + - match: { aggregations.test.buckets.0.key.long: 1000 } + - match: { aggregations.test.buckets.0.key.kw: "bar" } + - match: { aggregations.test.buckets.0.doc_count: 1 } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/TermsValuesSourceBuilder.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/TermsValuesSourceBuilder.java index 75bdd02855e..3ef871f59b9 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/TermsValuesSourceBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/TermsValuesSourceBuilder.java @@ -83,7 +83,9 @@ public class TermsValuesSourceBuilder extends CompositeValuesSourceBuilder config) throws IOException { ValuesSource vs = config.toValuesSource(context.getQueryShardContext()); if (vs == null) { - vs = ValuesSource.Numeric.EMPTY; + // The field is unmapped so we use a value source that can parse any type of values. + // This is needed because the after values are parsed even when there are no values to process. + vs = ValuesSource.Bytes.WithOrdinals.EMPTY; } final MappedFieldType fieldType = config.fieldContext() != null ? config.fieldContext().fieldType() : null; final DocValueFormat format;