parent
9333a3c28a
commit
6777be60ce
|
@ -2,7 +2,7 @@
|
||||||
=== Value Count
|
=== Value Count
|
||||||
|
|
||||||
A `single-value` metrics aggregation that counts the number of values that are extracted from the aggregated documents.
|
A `single-value` metrics aggregation that counts the number of values that are extracted from the aggregated documents.
|
||||||
These values can be extracted either from specific fields in the documents. Typically,
|
These values can be extracted either from specific fields in the documents, or be generated by a provided script. Typically,
|
||||||
this aggregator will be used in conjunction with other single-value aggregations. For example, when computing the `avg`
|
this aggregator will be used in conjunction with other single-value aggregations. For example, when computing the `avg`
|
||||||
one might be interested in the number of values the average is computed over.
|
one might be interested in the number of values the average is computed over.
|
||||||
|
|
||||||
|
@ -33,3 +33,17 @@ Response:
|
||||||
The name of the aggregation (`grades_count` above) also serves as the key by which the aggregation result can be
|
The name of the aggregation (`grades_count` above) also serves as the key by which the aggregation result can be
|
||||||
retrieved from the returned response.
|
retrieved from the returned response.
|
||||||
|
|
||||||
|
==== Script
|
||||||
|
|
||||||
|
Counting the values generated by a script:
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
--------------------------------------------------
|
||||||
|
{
|
||||||
|
...,
|
||||||
|
|
||||||
|
"aggs" : {
|
||||||
|
"grades_count" : { "value_count" : { "script" : "doc['grade'].value" } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--------------------------------------------------
|
|
@ -19,31 +19,15 @@
|
||||||
|
|
||||||
package org.elasticsearch.search.aggregations.metrics.valuecount;
|
package org.elasticsearch.search.aggregations.metrics.valuecount;
|
||||||
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.search.aggregations.metrics.ValuesSourceMetricsAggregationBuilder;
|
||||||
import org.elasticsearch.search.aggregations.metrics.MetricsAggregationBuilder;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ValueCountBuilder extends MetricsAggregationBuilder<ValueCountBuilder> {
|
public class ValueCountBuilder extends ValuesSourceMetricsAggregationBuilder<ValueCountBuilder> {
|
||||||
|
|
||||||
private String field;
|
|
||||||
|
|
||||||
public ValueCountBuilder(String name) {
|
public ValueCountBuilder(String name) {
|
||||||
super(name, InternalValueCount.TYPE.name());
|
super(name, InternalValueCount.TYPE.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueCountBuilder field(String field) {
|
|
||||||
this.field = field;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void internalXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
if (field != null) {
|
|
||||||
builder.field("field", field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.elasticsearch.search.aggregations.support.bytes.BytesValuesSource;
|
||||||
import org.elasticsearch.search.internal.SearchContext;
|
import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -47,6 +48,10 @@ public class ValueCountParser implements Aggregator.Parser {
|
||||||
ValuesSourceConfig<BytesValuesSource> config = new ValuesSourceConfig<BytesValuesSource>(BytesValuesSource.class);
|
ValuesSourceConfig<BytesValuesSource> config = new ValuesSourceConfig<BytesValuesSource>(BytesValuesSource.class);
|
||||||
|
|
||||||
String field = null;
|
String field = null;
|
||||||
|
String script = null;
|
||||||
|
String scriptLang = null;
|
||||||
|
Map<String, Object> scriptParams = null;
|
||||||
|
boolean assumeUnique = false;
|
||||||
|
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
String currentFieldName = null;
|
String currentFieldName = null;
|
||||||
|
@ -56,14 +61,36 @@ public class ValueCountParser implements Aggregator.Parser {
|
||||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||||
if ("field".equals(currentFieldName)) {
|
if ("field".equals(currentFieldName)) {
|
||||||
field = parser.text();
|
field = parser.text();
|
||||||
|
} else if ("script".equals(currentFieldName)) {
|
||||||
|
script = parser.text();
|
||||||
|
} else if ("lang".equals(currentFieldName)) {
|
||||||
|
scriptLang = parser.text();
|
||||||
} else {
|
} else {
|
||||||
throw new SearchParseException(context, "Unknown key for a " + token + " in [" + aggregationName + "]: [" + currentFieldName + "].");
|
throw new SearchParseException(context, "Unknown key for a " + token + " in [" + aggregationName + "]: [" + currentFieldName + "].");
|
||||||
}
|
}
|
||||||
|
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||||
|
if ("script_values_unique".equals(currentFieldName)) {
|
||||||
|
assumeUnique = parser.booleanValue();
|
||||||
|
} else {
|
||||||
|
throw new SearchParseException(context, "Unknown key for a " + token + " in [" + aggregationName + "]: [" + currentFieldName + "].");
|
||||||
|
}
|
||||||
|
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||||
|
if ("params".equals(currentFieldName)) {
|
||||||
|
scriptParams = parser.map();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new SearchParseException(context, "Unexpected token " + token + " in [" + aggregationName + "].");
|
throw new SearchParseException(context, "Unexpected token " + token + " in [" + aggregationName + "].");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (script != null) {
|
||||||
|
config.script(context.scriptService().search(context.lookup(), scriptLang, script, scriptParams));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assumeUnique) {
|
||||||
|
config.ensureUnique(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
return new ValueCountAggregator.Factory(aggregationName, config);
|
return new ValueCountAggregator.Factory(aggregationName, config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount;
|
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount;
|
||||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -124,4 +123,80 @@ public class ValueCountTests extends ElasticsearchIntegrationTest {
|
||||||
assertThat(valueCount.getName(), equalTo("count"));
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
assertThat(valueCount.getValue(), equalTo(20l));
|
assertThat(valueCount.getValue(), equalTo(20l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleValuedScript() throws Exception {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||||
|
.setQuery(matchAllQuery())
|
||||||
|
.addAggregation(count("count").script("doc['value'].value"))
|
||||||
|
.execute().actionGet();
|
||||||
|
|
||||||
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l));
|
||||||
|
|
||||||
|
ValueCount valueCount = searchResponse.getAggregations().get("count");
|
||||||
|
assertThat(valueCount, notNullValue());
|
||||||
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
|
assertThat(valueCount.getValue(), equalTo(10l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiValuedScript() throws Exception {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||||
|
.setQuery(matchAllQuery())
|
||||||
|
.addAggregation(count("count").script("doc['values'].values"))
|
||||||
|
.execute().actionGet();
|
||||||
|
|
||||||
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l));
|
||||||
|
|
||||||
|
ValueCount valueCount = searchResponse.getAggregations().get("count");
|
||||||
|
assertThat(valueCount, notNullValue());
|
||||||
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
|
assertThat(valueCount.getValue(), equalTo(20l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleValuedScriptWithParams() throws Exception {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||||
|
.setQuery(matchAllQuery())
|
||||||
|
.addAggregation(count("count").script("doc[s].value").param("s", "value"))
|
||||||
|
.execute().actionGet();
|
||||||
|
|
||||||
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l));
|
||||||
|
|
||||||
|
ValueCount valueCount = searchResponse.getAggregations().get("count");
|
||||||
|
assertThat(valueCount, notNullValue());
|
||||||
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
|
assertThat(valueCount.getValue(), equalTo(10l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiValuedScriptWithParams() throws Exception {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||||
|
.setQuery(matchAllQuery())
|
||||||
|
.addAggregation(count("count").script("doc[s].values").param("s", "values"))
|
||||||
|
.execute().actionGet();
|
||||||
|
|
||||||
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l));
|
||||||
|
|
||||||
|
ValueCount valueCount = searchResponse.getAggregations().get("count");
|
||||||
|
assertThat(valueCount, notNullValue());
|
||||||
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
|
assertThat(valueCount.getValue(), equalTo(20l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deduplication() throws Exception {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||||
|
.setQuery(matchAllQuery())
|
||||||
|
.addAggregation(count("count").script("doc['values'].values + [5L]"))
|
||||||
|
.execute().actionGet();
|
||||||
|
|
||||||
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l));
|
||||||
|
|
||||||
|
ValueCount valueCount = searchResponse.getAggregations().get("count");
|
||||||
|
assertThat(valueCount, notNullValue());
|
||||||
|
assertThat(valueCount.getName(), equalTo("count"));
|
||||||
|
assertThat(valueCount.getValue(), equalTo(28l));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue