Add shuffling xContent to aggregation tests

This commit is contained in:
Christoph Büscher 2016-04-05 13:06:47 +02:00
parent b86d0983bb
commit b01e3f0d3b
12 changed files with 82 additions and 37 deletions

View File

@ -57,7 +57,7 @@ public class FiltersAggregator extends BucketsAggregator {
public static final ParseField OTHER_BUCKET_FIELD = new ParseField("other_bucket");
public static final ParseField OTHER_BUCKET_KEY_FIELD = new ParseField("other_bucket_key");
public static class KeyedFilter implements Writeable<KeyedFilter>, ToXContent {
public static class KeyedFilter implements Writeable<KeyedFilter>, ToXContent, Comparable<KeyedFilter> {
static final KeyedFilter PROTOTYPE = new KeyedFilter("", EmptyQueryBuilder.PROTOTYPE);
private final String key;
@ -122,6 +122,11 @@ public class FiltersAggregator extends BucketsAggregator {
return Objects.equals(key, other.key)
&& Objects.equals(filter, other.filter);
}
@Override
public int compareTo(KeyedFilter o) {
return this.key.compareTo(o.key);
}
}
private final String[] keys;

View File

@ -25,14 +25,15 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.EmptyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AggregatorBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregator.KeyedFilter;
import org.elasticsearch.search.aggregations.support.AggregationContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@ -57,6 +58,8 @@ public class FiltersAggregatorBuilder extends AggregatorBuilder<FiltersAggregato
private FiltersAggregatorBuilder(String name, List<KeyedFilter> filters) {
super(name, InternalFilters.TYPE);
// internally we want to have a fixed order of filters, regardless of the order of the filters in the request
Collections.sort(filters);
this.filters = filters;
this.keyed = true;
}

View File

@ -42,8 +42,10 @@ import org.elasticsearch.search.sort.SortOrder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregatorBuilder> {
@ -58,7 +60,7 @@ public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregato
private HighlightBuilder highlightBuilder;
private List<String> fieldNames;
private List<String> fieldDataFields;
private List<ScriptField> scriptFields;
private Set<ScriptField> scriptFields;
private FetchSourceContext fetchSourceContext;
public TopHitsAggregatorBuilder(String name) {
@ -378,7 +380,7 @@ public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregato
throw new IllegalArgumentException("scriptField [script] must not be null: [" + name + "]");
}
if (scriptFields == null) {
scriptFields = new ArrayList<>();
scriptFields = new HashSet<>();
}
scriptFields.add(new ScriptField(name, script, ignoreFailure));
return this;
@ -389,7 +391,7 @@ public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregato
throw new IllegalArgumentException("[scriptFields] must not be null: [" + name + "]");
}
if (this.scriptFields == null) {
this.scriptFields = new ArrayList<>();
this.scriptFields = new HashSet<>();
}
this.scriptFields.addAll(scriptFields);
return this;
@ -398,7 +400,7 @@ public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregato
/**
* Gets the script fields.
*/
public List<ScriptField> scriptFields() {
public Set<ScriptField> scriptFields() {
return scriptFields;
}
@ -541,7 +543,7 @@ public class TopHitsAggregatorBuilder extends AggregatorBuilder<TopHitsAggregato
factory.highlightBuilder = in.readOptionalWriteable(HighlightBuilder::new);
if (in.readBoolean()) {
int size = in.readVInt();
List<ScriptField> scriptFields = new ArrayList<>(size);
Set<ScriptField> scriptFields = new HashSet<>(size);
for (int i = 0; i < size; i++) {
scriptFields.add(ScriptField.PROTOTYPE.readFrom(in));
}

View File

@ -42,6 +42,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregatorFactory> {
@ -54,12 +55,12 @@ public class TopHitsAggregatorFactory extends AggregatorFactory<TopHitsAggregato
private final HighlightBuilder highlightBuilder;
private final List<String> fieldNames;
private final List<String> fieldDataFields;
private final List<ScriptField> scriptFields;
private final Set<ScriptField> scriptFields;
private final FetchSourceContext fetchSourceContext;
public TopHitsAggregatorFactory(String name, Type type, int from, int size, boolean explain, boolean version, boolean trackScores,
List<SortBuilder<?>> sorts, HighlightBuilder highlightBuilder, List<String> fieldNames, List<String> fieldDataFields,
List<ScriptField> scriptFields, FetchSourceContext fetchSourceContext, AggregationContext context, AggregatorFactory<?> parent,
Set<ScriptField> scriptFields, FetchSourceContext fetchSourceContext, AggregationContext context, AggregatorFactory<?> parent,
AggregatorFactories.Builder subFactories, Map<String, Object> metaData) throws IOException {
super(name, type, context, parent, subFactories, metaData);
this.from = from;

View File

@ -39,9 +39,9 @@ import java.util.Objects;
public abstract class PipelineAggregatorBuilder<PAB extends PipelineAggregatorBuilder<PAB>> extends ToXContentToBytes
implements NamedWriteable<PipelineAggregatorBuilder<PAB>>, ToXContent {
protected String name;
protected String type;
protected String[] bucketsPaths;
protected final String name;
protected final String type;
protected final String[] bucketsPaths;
protected Map<String, Object> metaData;
/**

View File

@ -27,6 +27,7 @@ import org.elasticsearch.script.Script;
import org.elasticsearch.script.Script.ScriptField;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -24,9 +24,9 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.Script.ScriptField;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregatorBuilder;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.support.format.ValueFormat;
import org.elasticsearch.search.aggregations.support.format.ValueFormatter;
@ -34,8 +34,9 @@ import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
public class BucketScriptPipelineAggregatorBuilder extends PipelineAggregatorBuilder<BucketScriptPipelineAggregatorBuilder> {
@ -48,7 +49,8 @@ public class BucketScriptPipelineAggregatorBuilder extends PipelineAggregatorBui
private GapPolicy gapPolicy = GapPolicy.SKIP;
public BucketScriptPipelineAggregatorBuilder(String name, Map<String, String> bucketsPathsMap, Script script) {
super(name, BucketScriptPipelineAggregator.TYPE.name(), bucketsPathsMap.values().toArray(new String[bucketsPathsMap.size()]));
super(name, BucketScriptPipelineAggregator.TYPE.name(), new TreeMap<>(bucketsPathsMap).values()
.toArray(new String[bucketsPathsMap.size()]));
this.bucketsPathsMap = bucketsPathsMap;
this.script = script;
}

View File

@ -27,6 +27,7 @@ import org.elasticsearch.script.Script;
import org.elasticsearch.script.Script.ScriptField;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -24,17 +24,18 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.Script.ScriptField;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregatorBuilder;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.bucketscript.BucketScriptParser;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
public class BucketSelectorPipelineAggregatorBuilder extends PipelineAggregatorBuilder<BucketSelectorPipelineAggregatorBuilder> {
@ -43,10 +44,11 @@ public class BucketSelectorPipelineAggregatorBuilder extends PipelineAggregatorB
private Script script;
private GapPolicy gapPolicy = GapPolicy.SKIP;
private Map<String, String> bucketsPathsMap;
private final Map<String, String> bucketsPathsMap;
public BucketSelectorPipelineAggregatorBuilder(String name, Map<String, String> bucketsPathsMap, Script script) {
super(name, BucketSelectorPipelineAggregator.TYPE.name(), bucketsPathsMap.values().toArray(new String[bucketsPathsMap.size()]));
super(name, BucketSelectorPipelineAggregator.TYPE.name(), new TreeMap<>(bucketsPathsMap).values()
.toArray(new String[bucketsPathsMap.size()]));
this.bucketsPathsMap = bucketsPathsMap;
this.script = script;
}

View File

@ -36,8 +36,11 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.EnvironmentModule;
import org.elasticsearch.index.Index;
@ -215,8 +218,13 @@ public abstract class BaseAggregationTestCase<AB extends AggregatorBuilder<AB>>
public void testFromXContent() throws IOException {
AB testAgg = createTestAggregatorBuilder();
AggregatorFactories.Builder factoriesBuilder = AggregatorFactories.builder().addAggregator(testAgg);
String contentString = factoriesBuilder.toString();
XContentParser parser = XContentFactory.xContent(contentString).createParser(contentString);
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
if (randomBoolean()) {
builder.prettyPrint();
}
factoriesBuilder.toXContent(builder, ToXContent.EMPTY_PARAMS);
XContentBuilder shuffled = shuffleXContent(builder, Collections.emptySet());
XContentParser parser = XContentFactory.xContent(shuffled.bytes()).createParser(shuffled.bytes());
QueryParseContext parseContext = new QueryParseContext(queriesRegistry);
parseContext.reset(parser);
parseContext.parseFieldMatcher(parseFieldMatcher);

View File

@ -36,8 +36,11 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.EnvironmentModule;
import org.elasticsearch.index.Index;
@ -216,9 +219,14 @@ public abstract class BasePipelineAggregationTestCase<AF extends PipelineAggrega
public void testFromXContent() throws IOException {
AF testAgg = createTestAggregatorFactory();
AggregatorFactories.Builder factoriesBuilder = AggregatorFactories.builder().skipResolveOrder().addPipelineAggregator(testAgg);
String contentString = factoriesBuilder.toString();
logger.info("Content string: {}", contentString);
XContentParser parser = XContentFactory.xContent(contentString).createParser(contentString);
logger.info("Content string: {}", factoriesBuilder);
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
if (randomBoolean()) {
builder.prettyPrint();
}
factoriesBuilder.toXContent(builder, ToXContent.EMPTY_PARAMS);
XContentBuilder shuffled = shuffleXContent(builder, Collections.emptySet());
XContentParser parser = XContentFactory.xContent(shuffled.bytes()).createParser(shuffled.bytes());
QueryParseContext parseContext = new QueryParseContext(queriesRegistry);
parseContext.reset(parser);
parseContext.parseFieldMatcher(parseFieldMatcher);

View File

@ -112,7 +112,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testSimple() throws Exception {
SearchResponse response = client().prepareSearch("idx").addAggregation(
filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")), new KeyedFilter("tag2", termQuery("tag", "tag2"))))
filters("tags", randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))))
.execute().actionGet();
assertSearchResponse(response);
@ -137,7 +138,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testEmptyFilterDeclarations() throws Exception {
QueryBuilder<?> emptyFilter = new BoolQueryBuilder();
SearchResponse response = client().prepareSearch("idx")
.addAggregation(filters("tags", new KeyedFilter("all", emptyFilter), new KeyedFilter("tag1", termQuery("tag", "tag1"))))
.addAggregation(filters("tags", randomOrder(new KeyedFilter("all", emptyFilter),
new KeyedFilter("tag1", termQuery("tag", "tag1")))))
.execute().actionGet();
assertSearchResponse(response);
@ -154,8 +156,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testWithSubAggregation() throws Exception {
SearchResponse response = client().prepareSearch("idx")
.addAggregation(filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2"))).subAggregation(avg("avg_value").field("value")))
.addAggregation(filters("tags", randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))).subAggregation(avg("avg_value").field("value")))
.execute().actionGet();
assertSearchResponse(response);
@ -254,9 +256,9 @@ public class FiltersIT extends ESIntegTestCase {
try {
client().prepareSearch("idx")
.addAggregation(
filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")), new KeyedFilter("tag2", termQuery("tag", "tag2")))
.subAggregation(avg("avg_value"))
)
filters("tags",
randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))).subAggregation(avg("avg_value")))
.execute().actionGet();
fail("expected execution to fail - an attempt to have a context based numeric sub-aggregation, but there is not value source" +
@ -314,8 +316,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testOtherBucket() throws Exception {
SearchResponse response = client().prepareSearch("idx").addAggregation(
filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")), new KeyedFilter("tag2", termQuery("tag", "tag2")))
.otherBucket(true))
filters("tags", randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))).otherBucket(true))
.execute().actionGet();
assertSearchResponse(response);
@ -341,8 +343,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testOtherNamedBucket() throws Exception {
SearchResponse response = client().prepareSearch("idx")
.addAggregation(filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2"))).otherBucket(true).otherBucketKey("foobar"))
.addAggregation(filters("tags", randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))).otherBucket(true).otherBucketKey("foobar"))
.execute().actionGet();
assertSearchResponse(response);
@ -397,8 +399,8 @@ public class FiltersIT extends ESIntegTestCase {
public void testOtherWithSubAggregation() throws Exception {
SearchResponse response = client().prepareSearch("idx")
.addAggregation(filters("tags", new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2"))).otherBucket(true)
.addAggregation(filters("tags", randomOrder(new KeyedFilter("tag1", termQuery("tag", "tag1")),
new KeyedFilter("tag2", termQuery("tag", "tag2")))).otherBucket(true)
.subAggregation(avg("avg_value").field("value")))
.execute().actionGet();
@ -485,4 +487,14 @@ public class FiltersIT extends ESIntegTestCase {
assertThat(other.getDocCount(), is(0L));
}
private static KeyedFilter[] randomOrder(KeyedFilter... filters) {
for (int i = 0; i < filters.length; i++) {
KeyedFilter tmp = filters[i];
int index = randomInt(filters.length - 1);
filters[i] = filters[index];
filters[index] = tmp;
}
return filters;
}
}