From 3553522328282159fae20178ed65f89ef9b02a4b Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Thu, 9 Feb 2017 11:19:04 +0100 Subject: [PATCH] Add parameter to prefix aggs name with type in search responses (#22965) This pull request adds a new parameter to the REST Search API named `typed_keys`. When set to true, the aggregation names in the search response will be prefixed with a prefix that reflects the internal type of the aggregation. Here is a simple example: ``` GET /_search?typed_keys { "aggs": { "tweets_per_user": { "terms": { "field": "user" } } }, "size": 0 } ``` And the response: ``` { "aggs": { "sterms:tweets_per_user": { ... } } } ``` This parameter is intended to make life easier for REST clients that could parse back the prefix and could detect the type of the aggregation to parse. It could also be implemented for suggesters. --- .../action/search/RestMultiSearchAction.java | 9 + .../rest/action/search/RestSearchAction.java | 10 + .../aggregations/InternalAggregation.java | 15 ++ .../bucket/sampler/InternalSampler.java | 5 + .../significant/UnmappedSignificantTerms.java | 5 + .../bucket/terms/UnmappedTerms.java | 5 + .../SignificantTermsSignificanceScoreIT.java | 3 +- docs/reference/aggregations/misc.asciidoc | 86 +++++++ .../RestMultiSearchTemplateAction.java | 9 + .../mustache/RestSearchTemplateAction.java | 9 + .../test/lang_mustache/60_typed_keys.yaml | 119 +++++++++ .../resources/rest-api-spec/api/msearch.json | 4 + .../rest-api-spec/api/msearch_template.json | 4 + .../resources/rest-api-spec/api/search.json | 4 + .../rest-api-spec/api/search_template.json | 4 + .../test/msearch/20_typed_keys.yaml | 83 +++++++ .../search.aggregation/80_typed_keys.yaml | 226 ++++++++++++++++++ 17 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 modules/lang-mustache/src/test/resources/rest-api-spec/test/lang_mustache/60_typed_keys.yaml create mode 100644 rest-api-spec/src/main/resources/rest-api-spec/test/msearch/20_typed_keys.yaml create mode 100644 rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/80_typed_keys.yaml diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java index 856f878592d..8913fc637bb 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java @@ -39,7 +39,9 @@ import org.elasticsearch.rest.action.RestToXContentListener; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.io.IOException; +import java.util.Collections; import java.util.Map; +import java.util.Set; import java.util.function.BiConsumer; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; @@ -50,6 +52,8 @@ import static org.elasticsearch.rest.RestRequest.Method.POST; public class RestMultiSearchAction extends BaseRestHandler { + private static final Set RESPONSE_PARAMS = Collections.singleton("typed_keys"); + private final boolean allowExplicitIndex; public RestMultiSearchAction(Settings settings, RestController controller) { @@ -199,4 +203,9 @@ public class RestMultiSearchAction extends BaseRestHandler { } return -1; } + + @Override + protected Set responseParams() { + return RESPONSE_PARAMS; + } } diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java index 983f1b6dd55..fe2522f31d4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java @@ -44,6 +44,8 @@ import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode; import java.io.IOException; import java.util.Arrays; +import java.util.Collections; +import java.util.Set; import static org.elasticsearch.common.unit.TimeValue.parseTimeValue; import static org.elasticsearch.rest.RestRequest.Method.GET; @@ -51,6 +53,9 @@ import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.search.suggest.SuggestBuilders.termSuggestion; public class RestSearchAction extends BaseRestHandler { + + private static final Set RESPONSE_PARAMS = Collections.singleton("typed_keys"); + public RestSearchAction(Settings settings, RestController controller) { super(settings); controller.registerHandler(GET, "/_search", this); @@ -219,4 +224,9 @@ public class RestSearchAction extends BaseRestHandler { .suggestMode(SuggestMode.resolve(suggestMode)))); } } + + @Override + protected Set responseParams() { + return RESPONSE_PARAMS; + } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java b/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java index 752b3497a92..6dfd6fcc79f 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java @@ -38,6 +38,10 @@ import java.util.Objects; * An internal implementation of {@link Aggregation}. Serves as a base class for all aggregation implementations. */ public abstract class InternalAggregation implements Aggregation, ToXContent, NamedWriteable { + + /** Delimiter used when prefixing aggregation names with their type using the typed_keys parameter **/ + public static final String TYPED_KEYS_DELIMITER = "#"; + public static class ReduceContext { private final BigArrays bigArrays; @@ -149,8 +153,19 @@ public abstract class InternalAggregation implements Aggregation, ToXContent, Na return pipelineAggregators; } + /** + * Returns a string representing the type of the aggregation. This type is added to + * the aggregation name in the response, so that it can later be used by REST clients + * to determine the internal type of the aggregation. + */ + protected String getType() { + return getWriteableName(); + } + @Override public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + // Concatenates the type and the name of the aggregation (ex: top_hits#foo) + String name = params.paramAsBoolean("typed_keys", false) ? String.join(TYPED_KEYS_DELIMITER, getType(), getName()) : getName(); builder.startObject(name); if (this.metaData != null) { builder.field(CommonFields.META); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSampler.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSampler.java index 224de07e93d..e4473f9a517 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSampler.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSampler.java @@ -45,6 +45,11 @@ public class InternalSampler extends InternalSingleBucketAggregation implements return NAME; } + @Override + protected String getType() { + return "sampler"; + } + @Override protected InternalSingleBucketAggregation newAggregation(String name, long docCount, InternalAggregations subAggregations) { diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/UnmappedSignificantTerms.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/UnmappedSignificantTerms.java index 1a1094e62b4..e0b38140c43 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/UnmappedSignificantTerms.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/UnmappedSignificantTerms.java @@ -75,6 +75,11 @@ public class UnmappedSignificantTerms extends InternalSignificantTerms buckets) { return new UnmappedSignificantTerms(name, requiredSize, minDocCount, pipelineAggregators(), metaData); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/UnmappedTerms.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/UnmappedTerms.java index c3d1a8937c4..2613fc4159a 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/UnmappedTerms.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/UnmappedTerms.java @@ -71,6 +71,11 @@ public class UnmappedTerms extends InternalTerms buckets) { return new UnmappedTerms(name, order, requiredSize, minDocCount, pipelineAggregators(), metaData); diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java index 4a8c88b3093..7fc20908e81 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java @@ -23,6 +23,7 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; @@ -268,7 +269,7 @@ public class SignificantTermsSignificanceScoreIT extends ESIntegTestCase { XContentBuilder responseBuilder = XContentFactory.jsonBuilder(); responseBuilder.startObject(); - classes.toXContent(responseBuilder, null); + classes.toXContent(responseBuilder, ToXContent.EMPTY_PARAMS); responseBuilder.endObject(); String result = "{\"class\":{\"doc_count_error_upper_bound\":0,\"sum_other_doc_count\":0," diff --git a/docs/reference/aggregations/misc.asciidoc b/docs/reference/aggregations/misc.asciidoc index 7210daf1417..a3d9f61671a 100644 --- a/docs/reference/aggregations/misc.asciidoc +++ b/docs/reference/aggregations/misc.asciidoc @@ -82,3 +82,89 @@ Then that piece of metadata will be returned in place for our `titles` terms agg } -------------------------------------------------- // TESTRESPONSE[s/\.\.\./"took": "$body.took", "timed_out": false, "_shards": "$body._shards", "hits": "$body.hits"/] + + +[[returning-aggregation-type]] +== Returning the type of the aggregation + +Sometimes you need to know the exact type of an aggregation in order to parse its results. The `typed_keys` parameter + can be used to change the aggregation's name in the response so that it will be prefixed by its internal type. + +Considering the following <> named +`tweets_over_time` which has a sub <> named + `top_users`: + +[source,js] +-------------------------------------------------- +GET /twitter/tweet/_search?typed_keys +{ + "aggregations": { + "tweets_over_time": { + "date_histogram": { + "field": "date", + "interval": "year" + }, + "aggregations": { + "top_users": { + "top_hits": { + "size": 1 + } + } + } + } + } +} +-------------------------------------------------- +// CONSOLE +// TEST[setup:twitter] + +In the response, the aggregations names will be changed to respectively `date_histogram:tweets_over_time` and +`top_hits:top_users`, reflecting the internal types of each aggregation: + +[source,js] +-------------------------------------------------- +{ + "aggregations": { + "date_histogram#tweets_over_time": { <1> + "buckets" : [ + { + "key_as_string" : "2009-01-01T00:00:00.000Z", + "key" : 1230768000000, + "doc_count" : 5, + "top_hits#top_users" : { <2> + "hits" : { + "total" : 5, + "max_score" : 1.0, + "hits" : [ + { + "_index": "twitter", + "_type": "tweet", + "_id": "0", + "_score": 1.0, + "_source": { + "date": "2009-11-15T14:12:12", + "message": "trying out Elasticsearch", + "user": "kimchy", + "likes": 0 + } + } + ] + } + } + } + ] + } + }, + ... +} +-------------------------------------------------- +// TESTRESPONSE[s/\.\.\./"took": "$body.took", "timed_out": false, "_shards": "$body._shards", "hits": "$body.hits"/] + +<1> The name `tweets_over_time` now contains the `date_histogram` prefix. +<2> The name `top_users` now contains the `top_hits` prefix. + +NOTE: For some aggregations, it is possible that the returned type is not the same as the one provided with the +request. This is the case for Terms, Significant Terms and Percentiles aggregations, where the returned type +also contains information about the type of the targeted field: `lterms` (for a terms aggregation on a Long field), + `sigsterms` (for a significant terms aggregation on a String field), `tdigest_percentiles` (for a percentile + aggregation based on the TDigest algorithm). diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java index 30b18edb71b..835eea7fbf5 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java @@ -30,12 +30,16 @@ import org.elasticsearch.rest.action.RestToXContentListener; import org.elasticsearch.rest.action.search.RestMultiSearchAction; import java.io.IOException; +import java.util.Collections; +import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; public class RestMultiSearchTemplateAction extends BaseRestHandler { + private static final Set RESPONSE_PARAMS = Collections.singleton("typed_keys"); + private final boolean allowExplicitIndex; public RestMultiSearchTemplateAction(Settings settings, RestController controller) { @@ -86,4 +90,9 @@ public class RestMultiSearchTemplateAction extends BaseRestHandler { public boolean supportsContentStream() { return true; } + + @Override + protected Set responseParams() { + return RESPONSE_PARAMS; + } } diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java index bb263dd5a26..f1c1b15b2fa 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java @@ -37,12 +37,16 @@ import org.elasticsearch.rest.action.search.RestSearchAction; import org.elasticsearch.script.ScriptType; import java.io.IOException; +import java.util.Collections; +import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; public class RestSearchTemplateAction extends BaseRestHandler { + private static final Set RESPONSE_PARAMS = Collections.singleton("typed_keys"); + private static final ObjectParser PARSER; static { PARSER = new ObjectParser<>("search_template"); @@ -107,4 +111,9 @@ public class RestSearchTemplateAction extends BaseRestHandler { public static SearchTemplateRequest parse(XContentParser parser) throws IOException { return PARSER.parse(parser, new SearchTemplateRequest(), null); } + + @Override + protected Set responseParams() { + return RESPONSE_PARAMS; + } } diff --git a/modules/lang-mustache/src/test/resources/rest-api-spec/test/lang_mustache/60_typed_keys.yaml b/modules/lang-mustache/src/test/resources/rest-api-spec/test/lang_mustache/60_typed_keys.yaml new file mode 100644 index 00000000000..df9a42f87d5 --- /dev/null +++ b/modules/lang-mustache/src/test/resources/rest-api-spec/test/lang_mustache/60_typed_keys.yaml @@ -0,0 +1,119 @@ +setup: + - do: + indices.put_template: + name: index_template + body: + index_patterns: test-* + settings: + number_of_replicas: 0 + mappings: + user: + properties: + ip: + type: ip + integer: + type: integer + float: + type: float + name: + type: keyword + + - do: + bulk: + refresh: true + body: + - '{"index": {"_index": "test-0", "_type": "user"}}' + - '{"ip": "10.0.0.1", "integer": 38, "float": 12.5713, "name": "Ruth", "bool": true}' + - '{"index": {"_index": "test-0", "_type": "user"}}' + - '{"ip": "10.0.0.2", "integer": 42, "float": 15.3393, "name": "Jackie", "surname": "Bowling", "bool": false}' + - '{"index": {"_index": "test-1", "_type": "user"}}' + - '{"ip": "10.0.0.3", "integer": 29, "float": 19.0517, "name": "Stephanie", "bool": true}' + - '{"index": {"_index": "test-1", "_type": "user"}}' + - '{"ip": "10.0.0.4", "integer": 19, "float": 19.3717, "surname": "Hamilton", "bool": true}' + - '{"index": {"_index": "test-2", "_type": "user"}}' + - '{"ip": "10.0.0.5", "integer": 0, "float": 17.3349, "name": "Natalie", "bool": false}' + +--- +"Search template with typed_keys parameter": + + - do: + put_template: + id: template_1 + body: + template: + query: + match: + bool: "{{bool_value}}" + aggs: + test_missing: + missing: + field: "{{missing_field}}" + + - match: { acknowledged: true } + + - do: + search_template: + index: test-* + typed_keys: true + body: + id: template_1 + params: + bool_value: true + missing_field: name + + - match: { hits.total: 3 } + - match: { aggregations.missing#test_missing.doc_count: 1 } + +--- +"Multisearch template with typed_keys parameter": + + - do: + put_template: + id: registered_template + body: + template: + query: + range: + integer: + gte: "{{starting_value}}" + aggs: + test_histogram: + histogram: + field: "{{histo.field}}" + interval: "{{histo.interval}}" + + - match: { acknowledged: true } + + - do: + msearch_template: + typed_keys: true + body: + - index: test-* + - inline: + query: + match: + name: "{{name_value}}" + aggs: + test_global: + global: {} + aggs: + test_ip_range: + ip_range: + field: "{{ip_field}}" + ranges: + to: "10.0.0.6" + params: + name_value: "Stephanie" + ip_field: "ip" + - index: test-0,test-1 + - id: registered_template + params: + starting_value: 30 + histo: + field: float + interval: 5 + - match: { responses.0.hits.total: 1 } + - match: { responses.0.aggregations.global#test_global.doc_count: 5 } + - match: { responses.0.aggregations.global#test_global.ip_range#test_ip_range.buckets.0.doc_count: 5 } + - match: { responses.1.hits.total: 2 } + - match: { responses.1.aggregations.histogram#test_histogram.buckets.0.doc_count: 1 } diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/msearch.json b/rest-api-spec/src/main/resources/rest-api-spec/api/msearch.json index 0344702ecfe..87d5604cff1 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/msearch.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/msearch.json @@ -24,6 +24,10 @@ "max_concurrent_searches" : { "type" : "number", "description" : "Controls the maximum number of concurrent searches the multi search api will execute" + }, + "typed_keys": { + "type" : "boolean", + "description" : "Specify whether aggregation names should be prefixed by their respective types in the response" } } }, diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/msearch_template.json b/rest-api-spec/src/main/resources/rest-api-spec/api/msearch_template.json index 57e0e189668..b6254f4a5dd 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/msearch_template.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/msearch_template.json @@ -20,6 +20,10 @@ "type" : "enum", "options" : ["query_then_fetch", "query_and_fetch", "dfs_query_then_fetch", "dfs_query_and_fetch"], "description" : "Search operation type" + }, + "typed_keys": { + "type" : "boolean", + "description" : "Specify whether aggregation names should be prefixed by their respective types in the response" } } }, diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/search.json b/rest-api-spec/src/main/resources/rest-api-spec/api/search.json index 2cf359ede16..1807d252364 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/search.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/search.json @@ -147,6 +147,10 @@ "type" : "boolean", "description": "Whether to calculate and return scores even if they are not used for sorting" }, + "typed_keys": { + "type" : "boolean", + "description" : "Specify whether aggregation names should be prefixed by their respective types in the response" + }, "version": { "type" : "boolean", "description" : "Specify whether to return document version as part of a hit" diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/search_template.json b/rest-api-spec/src/main/resources/rest-api-spec/api/search_template.json index b9339b55332..904027623b6 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/search_template.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/search_template.json @@ -54,6 +54,10 @@ "profile": { "type" : "boolean", "description" : "Specify whether to profile the query execution" + }, + "typed_keys": { + "type" : "boolean", + "description" : "Specify whether aggregation names should be prefixed by their respective types in the response" } } }, diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/msearch/20_typed_keys.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/msearch/20_typed_keys.yaml new file mode 100644 index 00000000000..7f0fad201fc --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/msearch/20_typed_keys.yaml @@ -0,0 +1,83 @@ +setup: + - skip: + version: " - 5.3.99" + reason: typed_keys parameter was added in 5.4.0 + + - do: + indices.put_template: + name: index_template + body: + index_patterns: test-* + settings: + number_of_replicas: 0 + mappings: + user: + properties: + index_start_at: + type: integer + integer: + type: integer + float: + type: float + name: + type: keyword + + - do: + bulk: + refresh: true + body: + - '{"index": {"_index": "test-0", "_type": "user"}}' + - '{"row": 1, "index_start_at": 56, "integer": 38, "float": 12.5713, "name": "Ruth", "bool": true}' + - '{"index": {"_index": "test-0", "_type": "user"}}' + - '{"row": 2, "index_start_at": 57, "integer": 42, "float": 15.3393, "name": "Jackie", "surname": "Bowling", "bool": false}' + - '{"index": {"_index": "test-1", "_type": "user"}}' + - '{"row": 3, "index_start_at": 58, "integer": 29, "float": 19.0517, "name": "Stephanie", "bool": true}' + - '{"index": {"_index": "test-1", "_type": "user"}}' + - '{"row": 4, "index_start_at": 59, "integer": 19, "float": 19.3717, "surname": "Hamilton", "bool": true}' + - '{"index": {"_index": "test-2", "_type": "user"}}' + - '{"row": 5, "index_start_at": 60, "integer": 0, "float": 17.3349, "name": "Natalie", "bool": false}' + +--- +"Multisearch test with typed_keys parameter": + - do: + msearch: + typed_keys: true + body: + - index: test-* + - {query: {match: {bool: true} }, size: 0, aggs: {test_filter: {filter: {range:{integer: {gte: 20} } } } } } + - index: test-1 + - {query: {match_all: {} }, size: 0, aggs: {test_range: {range: {field: float, ranges: [ {to: 19.2499999}, {from: 19.25} ] } } } } + - index: test-* + - {query: {bool: {filter: {range: {row: {lt: 5}}} } }, size: 0, aggs: {test_percentiles: {percentiles: {field: float} } } } + + - match: { responses.0.hits.total: 3 } + - match: { responses.0.aggregations.filter#test_filter.doc_count : 2 } + - match: { responses.1.hits.total: 2 } + - match: { responses.1.aggregations.range#test_range.buckets.0.key : "*-19.2499999" } + - match: { responses.1.aggregations.range#test_range.buckets.0.doc_count : 1 } + - match: { responses.1.aggregations.range#test_range.buckets.1.key : "19.25-*" } + - match: { responses.1.aggregations.range#test_range.buckets.1.doc_count : 1 } + - match: { responses.2.hits.total: 4 } + - is_true: responses.2.aggregations.tdigest_percentiles#test_percentiles.values + +--- +"Multisearch test with typed_keys parameter for sampler and significant terms": + - do: + msearch: + typed_keys: true + body: + - index: test-* + - {query: {match_all: {} }, size: 0, aggs: {test_sampler: {sampler: {shard_size: 200}, aggs: {test_significant_terms: {significant_terms: {field: name} } } } } } + - index: test-* + - {query: {match_all: {} }, size: 0, aggs: {test_umterms: {terms: {field: surname} } } } + - index: test-* + - {query: {match_all: {} }, size: 0, aggs: {test_sterms: {terms: {field: name}, aggs: {test_umsignificant_terms: {significant_terms: {field: surname} } } } } } + + - match: { responses.0.hits.total: 5 } + - match: { responses.0.aggregations.sampler#test_sampler.doc_count : 5 } + - match: { responses.0.aggregations.sampler#test_sampler.sigsterms#test_significant_terms.doc_count : 5 } + - match: { responses.1.hits.total: 1 } + - match: { responses.1.aggregations.sterms#test_umterms.doc_count_error_upper_bound : 0 } + - match: { responses.2.hits.total: 1 } + - match: { responses.2.aggregations.sterms#test_sterms.doc_count_error_upper_bound : 0 } + - is_true: responses.2.aggregations.sterms#test_sterms.buckets.0.sigsterms#test_umsignificant_terms diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/80_typed_keys.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/80_typed_keys.yaml new file mode 100644 index 00000000000..9ea856c856e --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/80_typed_keys.yaml @@ -0,0 +1,226 @@ +setup: + - skip: + version: " - 5.3.99" + reason: typed_keys parameter was added in 5.4.0 + + - do: + indices.create: + index: test + body: + settings: + number_of_replicas: 0 + mappings: + test: + properties: + name: + type: keyword + num: + type: integer + created: + type: date + + - do: + bulk: + refresh: true + index: test + type: test + body: + - '{"index": {}}' + - '{"name": "one", "num": 1, "created": "2010-03-12T01:07:45"}' + - '{"index": {}}' + - '{"name": "two", "num": 2, "created": "2010-03-12T04:11:00"}' + - '{"index": {}}' + - '{"name": "three", "num": 3, "created": "2010-04-27T03:43:34"}' + +--- +"Test typed keys parameter for avg aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_avg: + avg: + field: num + - is_true: aggregations.avg#test_avg + +--- +"Test typed keys parameter for cardinality aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_cardinality: + cardinality: + field: name + - is_true: aggregations.cardinality#test_cardinality + +--- +"Test typed keys parameter for extended_stats aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_extended_stats: + extended_stats: + field: num + - is_true: aggregations.extended_stats#test_extended_stats + +--- +"Test typed keys parameter for max aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_max: + max: + field: num + - is_true: aggregations.max#test_max + +--- +"Test typed keys parameter for min aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_min: + min: + field: num + - is_true: aggregations.min#test_min + +--- +"Test typed keys parameter for percentiles aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_percentiles: + percentiles: + field: num + - is_true: aggregations.tdigest_percentiles#test_percentiles + +--- +"Test typed keys parameter for percentile_ranks aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_percentile_ranks: + percentile_ranks: + field: num + values: [0,10] + - is_true: aggregations.tdigest_percentile_ranks#test_percentile_ranks + +--- +"Test typed keys parameter for stats aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_stats: + stats: + field: num + - is_true: aggregations.stats#test_stats + +--- +"Test typed keys parameter for sum aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_sum: + sum: + field: num + - is_true: aggregations.sum#test_sum + +--- +"Test typed keys parameter for terms and top_hits aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_terms: + terms: + field: name + aggs: + test_top_hits: + top_hits: + sort: num + - is_true: aggregations.sterms#test_terms + - is_true: aggregations.sterms#test_terms.buckets.0.top_hits#test_top_hits + - is_true: aggregations.sterms#test_terms.buckets.1.top_hits#test_top_hits + - is_true: aggregations.sterms#test_terms.buckets.2.top_hits#test_top_hits + +--- +"Test typed keys parameter for terms aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_terms: + terms: + field: num + - is_true: aggregations.lterms#test_terms + +--- +"Test typed keys parameter for value_count aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_value_count: + value_count: + field: num + - is_true: aggregations.value_count#test_value_count + +--- +"Test typed keys parameter for date_histogram aggregation and max_bucket pipeline aggregation": + - do: + search: + typed_keys: true + body: + size: 0 + aggregations: + test_created_histogram: + date_histogram: + field: created + interval: month + aggregations: + test_sum: + sum: + field: num + test_moving_avg: + moving_avg: + buckets_path: "test_sum" + test_max_bucket: + max_bucket: + buckets_path: "test_created_histogram>test_sum" + + - is_true: aggregations.date_histogram#test_created_histogram + - is_true: aggregations.date_histogram#test_created_histogram.buckets.0.sum#test_sum + - is_true: aggregations.date_histogram#test_created_histogram.buckets.1.sum#test_sum + - is_true: aggregations.date_histogram#test_created_histogram.buckets.1.simple_value#test_moving_avg + - is_true: aggregations.bucket_metric_value#test_max_bucket