Added global ordinals terms aggregator impl that is optimized low cardinality fields.

Instead of resolving the global ordinal for each hit on the fly, resolve the global ordinals during post collect.
On fields with not so many unique values, that can reduce the number of global ordinals significantly.

Closes #5895
Closes #5854
This commit is contained in:
Martijn van Groningen 2014-04-22 13:24:34 +07:00
parent 4df4506875
commit f3219f7098
7 changed files with 192 additions and 44 deletions

View File

@ -124,7 +124,7 @@ public class InternalGlobalOrdinalsBuilder extends AbstractIndexComponent implem
}
private static abstract class GlobalOrdinalMapping implements Ordinals.Docs {
public static abstract class GlobalOrdinalMapping implements Ordinals.Docs {
protected final Ordinals.Docs segmentOrdinals;
private final long memorySizeInBytes;
@ -174,7 +174,7 @@ public class InternalGlobalOrdinalsBuilder extends AbstractIndexComponent implem
return currentGlobalOrd = getGlobalOrd(segmentOrd);
}
protected abstract long getGlobalOrd(long segmentOrd);
public abstract long getGlobalOrd(long segmentOrd);
}
@ -289,7 +289,7 @@ public class InternalGlobalOrdinalsBuilder extends AbstractIndexComponent implem
}
@Override
protected long getGlobalOrd(long segmentOrd) {
public long getGlobalOrd(long segmentOrd) {
return segmentOrd + segmentOrdToGlobalOrdLookup.get(segmentOrd);
}
}
@ -323,7 +323,7 @@ public class InternalGlobalOrdinalsBuilder extends AbstractIndexComponent implem
}
@Override
protected long getGlobalOrd(long segmentOrd) {
public long getGlobalOrd(long segmentOrd) {
return segmentOrd + segmentOrdToGlobalOrdLookup.get((int) segmentOrd);
}
}

View File

@ -78,11 +78,8 @@ public abstract class BucketsAggregator extends Aggregator {
}
}
/**
* Initializes the docCounts to the specified size.
*/
public void initializeDocCounts(long maxOrd) {
docCounts = bigArrays.grow(docCounts, maxOrd);
public LongArray getDocCounts() {
return docCounts;
}
/**
@ -97,7 +94,7 @@ public abstract class BucketsAggregator extends Aggregator {
/**
* Utility method to increment the doc counts of the given bucket (identified by the bucket ordinal)
*/
protected final void incrementBucketDocCount(int inc, long bucketOrd) throws IOException {
protected final void incrementBucketDocCount(long inc, long bucketOrd) throws IOException {
docCounts = bigArrays.grow(docCounts, bucketOrd + 1);
docCounts.increment(bucketOrd, inc);
}

View File

@ -23,7 +23,9 @@ import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.RamUsageEstimator;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.util.LongArray;
import org.elasticsearch.common.util.LongHash;
import org.elasticsearch.index.fielddata.BytesValues;
import org.elasticsearch.index.fielddata.ordinals.Ordinals;
@ -37,6 +39,8 @@ import org.elasticsearch.search.aggregations.support.ValuesSource;
import java.io.IOException;
import java.util.Arrays;
import static org.elasticsearch.index.fielddata.ordinals.InternalGlobalOrdinalsBuilder.GlobalOrdinalMapping;
/**
* An aggregator of string values that relies on global ordinals in order to build buckets.
*/
@ -47,8 +51,8 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
protected Ordinals.Docs globalOrdinals;
public GlobalOrdinalsStringTermsAggregator(String name, AggregatorFactories factories, ValuesSource.Bytes.WithOrdinals.FieldData valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, AggregationContext aggregationContext, Aggregator parent) {
super(name, factories, estimatedBucketCount, aggregationContext, parent, order, requiredSize, shardSize, minDocCount);
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, AggregationContext aggregationContext, Aggregator parent) {
super(name, factories, maxOrd, aggregationContext, parent, order, requiredSize, shardSize, minDocCount);
this.valuesSource = valuesSource;
}
@ -65,7 +69,6 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
public void setNextReader(AtomicReaderContext reader) {
globalValues = valuesSource.globalBytesValues();
globalOrdinals = globalValues.ordinals();
initializeDocCounts(globalOrdinals.getMaxOrd());
}
@Override
@ -135,9 +138,10 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
private final LongHash bucketOrds;
public WithHash(String name, AggregatorFactories factories, ValuesSource.Bytes.WithOrdinals.FieldData valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, AggregationContext aggregationContext,
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, AggregationContext aggregationContext,
Aggregator parent) {
super(name, factories, valuesSource, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
// Set maxOrd to estimatedBucketCount! To be conservative with memory.
super(name, factories, valuesSource, estimatedBucketCount, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
bucketOrds = new LongHash(estimatedBucketCount, aggregationContext.bigArrays());
}
@ -172,4 +176,78 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
}
/**
* Variant of {@link GlobalOrdinalsStringTermsAggregator} that resolves global ordinals post segment collection
* instead of on the fly for each match.This is beneficial for low cardinality fields, because it can reduce
* the amount of look-ups significantly.
*/
public static class LowCardinality extends GlobalOrdinalsStringTermsAggregator {
private final LongArray segmentDocCounts;
private Ordinals.Docs segmentOrdinals;
private LongArray current;
public LowCardinality(String name, AggregatorFactories factories, ValuesSource.Bytes.WithOrdinals.FieldData valuesSource, long estimatedBucketCount,
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, AggregationContext aggregationContext, Aggregator parent) {
super(name, factories, valuesSource, estimatedBucketCount, maxOrd, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
this.segmentDocCounts = bigArrays.newLongArray(maxOrd, true);
}
@Override
public void collect(int doc, long owningBucketOrdinal) throws IOException {
final int numOrds = segmentOrdinals.setDocument(doc);
for (int i = 0; i < numOrds; i++) {
final long segmentOrd = segmentOrdinals.nextOrd();
current.increment(segmentOrd, 1);
}
}
@Override
public void setNextReader(AtomicReaderContext reader) {
if (segmentOrdinals != null && segmentOrdinals.getMaxOrd() != globalOrdinals.getMaxOrd()) {
mapSegmentCountsToGlobalCounts();
}
super.setNextReader(reader);
BytesValues.WithOrdinals bytesValues = valuesSource.bytesValues();
segmentOrdinals = bytesValues.ordinals();
if (segmentOrdinals.getMaxOrd() != globalOrdinals.getMaxOrd()) {
current = segmentDocCounts;
} else {
current = getDocCounts();
}
}
@Override
protected void doPostCollection() {
if (segmentOrdinals.getMaxOrd() != globalOrdinals.getMaxOrd()) {
mapSegmentCountsToGlobalCounts();
}
}
@Override
protected void doClose() {
Releasables.close(segmentDocCounts);
}
private void mapSegmentCountsToGlobalCounts() {
// There is no public method in Ordinals.Docs that allows for this mapping...
// This is the cleanest way I can think of so far
GlobalOrdinalMapping mapping = (GlobalOrdinalMapping) globalOrdinals;
for (int i = 0; i < segmentDocCounts.size(); i++) {
final long inc = segmentDocCounts.set(i, 0);
if (inc == 0) {
continue;
}
final long globalOrd = mapping.getGlobalOrd(i);
try {
incrementBucketDocCount(inc, globalOrd);
} catch (IOException e) {
throw ExceptionsHelper.convertToElastic(e);
}
}
}
}
}

View File

@ -18,6 +18,7 @@
*/
package org.elasticsearch.search.aggregations.bucket.terms;
import org.apache.lucene.search.IndexSearcher;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.search.aggregations.*;
@ -39,8 +40,8 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
@Override
Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
return new StringTermsAggregator(name, factories, valuesSource, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, includeExclude, aggregationContext, parent);
}
@ -54,8 +55,8 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
@Override
Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
if (includeExclude != null) {
throw new ElasticsearchIllegalArgumentException("The `" + this + "` execution mode cannot filter terms.");
}
@ -72,12 +73,12 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
@Override
Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
if (includeExclude != null) {
throw new ElasticsearchIllegalArgumentException("The `" + this + "` execution mode cannot filter terms.");
}
return new GlobalOrdinalsStringTermsAggregator(name, factories, (ValuesSource.Bytes.WithOrdinals.FieldData) valuesSource, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
return new GlobalOrdinalsStringTermsAggregator(name, factories, (ValuesSource.Bytes.WithOrdinals.FieldData) valuesSource, estimatedBucketCount, maxOrd, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
}
@Override
@ -90,12 +91,32 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
@Override
Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
if (includeExclude != null) {
throw new ElasticsearchIllegalArgumentException("The `" + this + "` execution mode cannot filter terms.");
}
return new GlobalOrdinalsStringTermsAggregator.WithHash(name, factories, (ValuesSource.Bytes.WithOrdinals.FieldData) valuesSource, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
return new GlobalOrdinalsStringTermsAggregator.WithHash(name, factories, (ValuesSource.Bytes.WithOrdinals.FieldData) valuesSource, estimatedBucketCount, maxOrd, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
}
@Override
boolean needsGlobalOrdinals() {
return true;
}
},
GLOBAL_ORDINALS_LOW_CARDINALITY(new ParseField("global_ordinals_low_cardinality")) {
@Override
Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount, IncludeExclude includeExclude,
AggregationContext aggregationContext, Aggregator parent) {
if (includeExclude != null) {
throw new ElasticsearchIllegalArgumentException("The `" + this + "` execution mode cannot filter terms.");
}
if (factories != AggregatorFactories.EMPTY) {
throw new ElasticsearchIllegalArgumentException("The `" + this + "` execution mode can only be used as a leaf aggregation");
}
return new GlobalOrdinalsStringTermsAggregator.LowCardinality(name, factories, (ValuesSource.Bytes.WithOrdinals.FieldData) valuesSource, estimatedBucketCount, maxOrd, order, requiredSize, shardSize, minDocCount, aggregationContext, parent);
}
@Override
@ -120,8 +141,8 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
}
abstract Aggregator create(String name, AggregatorFactories factories, ValuesSource valuesSource, long estimatedBucketCount,
InternalOrder order, int requiredSize, int shardSize, long minDocCount,
IncludeExclude includeExclude, AggregationContext aggregationContext, Aggregator parent);
long maxOrd, InternalOrder order, int requiredSize, int shardSize, long minDocCount,
IncludeExclude includeExclude, AggregationContext aggregationContext, Aggregator parent);
abstract boolean needsGlobalOrdinals();
@ -200,6 +221,18 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
execution = ExecutionMode.MAP;
}
final long maxOrd;
final double ratio;
if (execution == null || execution.needsGlobalOrdinals()) {
ValuesSource.Bytes.WithOrdinals valueSourceWithOrdinals = (ValuesSource.Bytes.WithOrdinals) valuesSource;
IndexSearcher indexSearcher = aggregationContext.searchContext().searcher();
maxOrd = valueSourceWithOrdinals.globalMaxOrd(indexSearcher);
ratio = maxOrd / ((double) indexSearcher.getIndexReader().numDocs());
} else {
maxOrd = -1;
ratio = -1;
}
// Let's try to use a good default
if (execution == null) {
// if there is a parent bucket aggregator the number of instances of this aggregator is going
@ -208,12 +241,23 @@ public class TermsAggregatorFactory extends ValuesSourceAggregatorFactory {
if (hasParentBucketAggregator(parent)) {
execution = ExecutionMode.GLOBAL_ORDINALS_HASH;
} else {
execution = ExecutionMode.GLOBAL_ORDINALS;
if (factories == AggregatorFactories.EMPTY) {
if (ratio <= 0.5 && maxOrd <= 2048) {
// 0.5: At least we need reduce the number of global ordinals look-ups by half
// 2048: GLOBAL_ORDINALS_LOW_CARDINALITY has additional memory usage, which directly linked to maxOrd, so we need to limit.
execution = ExecutionMode.GLOBAL_ORDINALS_LOW_CARDINALITY;
} else {
execution = ExecutionMode.GLOBAL_ORDINALS;
}
} else {
execution = ExecutionMode.GLOBAL_ORDINALS;
}
}
}
assert execution != null;
valuesSource.setNeedsGlobalOrdinals(execution.needsGlobalOrdinals());
return execution.create(name, factories, valuesSource, estimatedBucketCount, order, requiredSize, shardSize, minDocCount, includeExclude, aggregationContext, parent);
return execution.create(name, factories, valuesSource, estimatedBucketCount, maxOrd, order, requiredSize, shardSize, minDocCount, includeExclude, aggregationContext, parent);
}
if (includeExclude != null) {

View File

@ -19,7 +19,9 @@
package org.elasticsearch.search.aggregations.support;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefArray;
@ -29,6 +31,7 @@ import org.elasticsearch.common.lucene.TopReaderContextAware;
import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.index.fielddata.*;
import org.elasticsearch.index.fielddata.AtomicFieldData.Order;
import org.elasticsearch.index.fielddata.ordinals.Ordinals;
import org.elasticsearch.script.SearchScript;
import org.elasticsearch.search.aggregations.support.ValuesSource.Bytes.SortedAndUnique.SortedUniqueBytesValues;
import org.elasticsearch.search.aggregations.support.values.ScriptBytesValues;
@ -159,6 +162,8 @@ public abstract class ValuesSource {
public abstract BytesValues.WithOrdinals globalBytesValues();
public abstract long globalMaxOrd(IndexSearcher indexSearcher);
public static class FieldData extends WithOrdinals implements ReaderContextAware {
protected boolean needsHashes;
@ -229,6 +234,21 @@ public abstract class ValuesSource {
}
return globalBytesValues;
}
@Override
public long globalMaxOrd(IndexSearcher indexSearcher) {
IndexReader indexReader = indexSearcher.getIndexReader();
if (indexReader.leaves().isEmpty()) {
return 0;
} else {
AtomicReaderContext atomicReaderContext = indexReader.leaves().get(0);
IndexFieldData.WithOrdinals<?> globalFieldData = indexFieldData.loadGlobal(indexReader);
AtomicFieldData.WithOrdinals afd = globalFieldData.load(atomicReaderContext);
BytesValues.WithOrdinals values = afd.getBytesValues(false);
Ordinals.Docs ordinals = values.ordinals();
return ordinals.getMaxOrd();
}
}
}
}

View File

@ -186,7 +186,7 @@ public class GlobalOrdinalsBenchmark {
fieldName = fieldName + ".doc_values";
name = name + "_doc_values"; // can't have . in agg name
}
stats.add(terms(name, fieldName, "global_ordinals"));
stats.add(terms(name, fieldName, "global_ordinals_low_cardinality"));
}
}

View File

@ -36,6 +36,7 @@ import org.hamcrest.Matchers;
import org.junit.Test;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
@ -59,6 +60,12 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
private static final String MULTI_VALUED_FIELD_NAME = "s_values";
public static String randomExecutionHint() {
EnumSet<ExecutionMode> modes = EnumSet.allOf(ExecutionMode.class);
modes.remove(ExecutionMode.GLOBAL_ORDINALS_LOW_CARDINALITY);
return randomBoolean() ? null : randomFrom(modes.toArray()).toString();
}
public static String randomAllExecutionHint() {
return randomBoolean() ? null : randomFrom(ExecutionMode.values()).toString();
}
@ -106,7 +113,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
final int minDocCount = randomInt(1);
SearchResponse response = client().prepareSearch("idx").setTypes("high_card_type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.minDocCount(minDocCount)
.size(0))
@ -146,14 +153,16 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
@Test
public void singleValueField_withGlobalOrdinals() throws Exception {
ExecutionMode[] executionModes = new ExecutionMode[] {
null,
ExecutionMode.GLOBAL_ORDINALS,
ExecutionMode.GLOBAL_ORDINALS_HASH
ExecutionMode.GLOBAL_ORDINALS_HASH,
ExecutionMode.GLOBAL_ORDINALS_LOW_CARDINALITY
};
for (ExecutionMode executionMode : executionModes) {
logger.info("Execution mode:" + executionMode);
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(executionMode.toString())
.executionHint(executionMode == null ? null : executionMode.toString())
.field(SINGLE_VALUED_FIELD_NAME))
.execute().actionGet();
assertSearchResponse(response);
@ -319,7 +328,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void singleValueField_WithMaxSize() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("high_card_type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.size(20)
.order(Terms.Order.term(true))) // we need to sort by terms cause we're checking the first 20 values
@ -344,7 +353,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void singleValueField_OrderedByTermAsc() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.order(Terms.Order.term(true)))
.execute().actionGet();
@ -369,7 +378,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void singleValueField_OrderedByTermDesc() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.order(Terms.Order.term(false)))
.execute().actionGet();
@ -448,7 +457,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void singleValuedField_WithValueScript() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.script("'foo_' + _value"))
.execute().actionGet();
@ -472,7 +481,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void multiValuedField_WithValueScript_NotUnique() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(MULTI_VALUED_FIELD_NAME)
.script("_value.substring(0,3)"))
.execute().actionGet();
@ -494,7 +503,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void multiValuedField() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(MULTI_VALUED_FIELD_NAME))
.execute().actionGet();
@ -521,7 +530,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void multiValuedField_WithValueScript() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(MULTI_VALUED_FIELD_NAME)
.script("'foo_' + _value"))
.execute().actionGet();
@ -602,7 +611,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void script_SingleValue() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.script("doc['" + SINGLE_VALUED_FIELD_NAME + "'].value"))
.execute().actionGet();
@ -625,7 +634,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void script_SingleValue_ExplicitSingleValue() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.script("doc['" + SINGLE_VALUED_FIELD_NAME + "'].value"))
.execute().actionGet();
@ -675,7 +684,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void script_MultiValued() throws Exception {
SearchResponse response = client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.script("doc['" + MULTI_VALUED_FIELD_NAME + "'].values"))
.execute().actionGet();
@ -736,7 +745,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void unmapped() throws Exception {
SearchResponse response = client().prepareSearch("idx_unmapped").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.size(randomInt(5))
.field(SINGLE_VALUED_FIELD_NAME))
.execute().actionGet();
@ -753,7 +762,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
public void partiallyUnmapped() throws Exception {
SearchResponse response = client().prepareSearch("idx", "idx_unmapped").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME))
.execute().actionGet();
@ -947,7 +956,7 @@ public class StringTermsTests extends ElasticsearchIntegrationTest {
client().prepareSearch("idx").setTypes("type")
.addAggregation(terms("terms")
.executionHint(randomExecutionHint())
.executionHint(randomAllExecutionHint())
.field(SINGLE_VALUED_FIELD_NAME)
.order(Terms.Order.aggregation("avg_i", true))
).execute().actionGet();