Add parent-join module (#24638)
* Add parent-join module This change adds a new module named `parent-join`. The goal of this module is to provide a replacement for the `_parent` field but as a first step this change only moves the `has_child`, `has_parent` queries and the `children` aggregation to this module. These queries and aggregations are no longer in core but they are deployed by default as a module. Relates #20257
This commit is contained in:
parent
be2a6ce80b
commit
279a18a527
|
@ -138,6 +138,7 @@ subprojects {
|
|||
"org.elasticsearch.plugin:transport-netty4-client:${version}": ':modules:transport-netty4',
|
||||
"org.elasticsearch.plugin:reindex-client:${version}": ':modules:reindex',
|
||||
"org.elasticsearch.plugin:lang-mustache-client:${version}": ':modules:lang-mustache',
|
||||
"org.elasticsearch.plugin:parent-join-client:${version}": ':modules:parent-join',
|
||||
"org.elasticsearch.plugin:percolator-client:${version}": ':modules:percolator',
|
||||
]
|
||||
project.afterEvaluate {
|
||||
|
|
|
@ -620,7 +620,6 @@
|
|||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]BoolQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]BoostingQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]GeoDistanceQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]HasChildQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]MoreLikeThisQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]MultiMatchQueryBuilderTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]index[/\\]query[/\\]SpanMultiTermQueryBuilderTests.java" checks="LineLength" />
|
||||
|
@ -689,7 +688,6 @@
|
|||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]MultiValueModeTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]SearchWithRejectionsIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]aggregations[/\\]MissingValueIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]aggregations[/\\]bucket[/\\]ChildrenIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]aggregations[/\\]bucket[/\\]DateHistogramIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]aggregations[/\\]bucket[/\\]DateHistogramOffsetIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]aggregations[/\\]bucket[/\\]GeoDistanceIT.java" checks="LineLength" />
|
||||
|
@ -716,7 +714,6 @@
|
|||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]SearchWithRandomExceptionsIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]SearchWithRandomIOExceptionsIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]TransportTwoNodesSearchIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]child[/\\]ChildQuerySearchIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]child[/\\]ParentFieldLoadingIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]geo[/\\]GeoBoundingBoxIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]geo[/\\]GeoFilterIT.java" checks="LineLength" />
|
||||
|
|
|
@ -51,8 +51,6 @@ import static org.elasticsearch.index.query.QueryBuilders.geoBoundingBoxQuery;
|
|||
import static org.elasticsearch.index.query.QueryBuilders.geoDistanceQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.geoPolygonQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.idsQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
|
@ -216,24 +214,6 @@ public class QueryDSLDocumentationTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testHasChild() {
|
||||
// tag::has_child
|
||||
hasChildQuery(
|
||||
"blog_tag", // <1>
|
||||
termQuery("tag","something"), // <2>
|
||||
ScoreMode.None); // <3>
|
||||
// end::has_child
|
||||
}
|
||||
|
||||
public void testHasParent() {
|
||||
// tag::has_parent
|
||||
hasParentQuery(
|
||||
"blog", // <1>
|
||||
termQuery("tag","something"), // <2>
|
||||
false); // <3>
|
||||
// end::has_parent
|
||||
}
|
||||
|
||||
public void testIds() {
|
||||
// tag::ids
|
||||
idsQuery("my_type", "type2")
|
||||
|
|
|
@ -31,6 +31,7 @@ dependencies {
|
|||
compile "org.elasticsearch.plugin:reindex-client:${version}"
|
||||
compile "org.elasticsearch.plugin:lang-mustache-client:${version}"
|
||||
compile "org.elasticsearch.plugin:percolator-client:${version}"
|
||||
compile "org.elasticsearch.plugin:parent-join-client:${version}"
|
||||
testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
|
||||
testCompile "junit:junit:${versions.junit}"
|
||||
testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"
|
||||
|
|
|
@ -195,7 +195,8 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
|
|||
}
|
||||
}
|
||||
|
||||
InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType, boolean ignoreUnmapped) {
|
||||
// NORELEASE Do not use this ctr, it is public for hasChild and hasParent query but this is temporary
|
||||
public InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType, boolean ignoreUnmapped) {
|
||||
this(other);
|
||||
this.query = query;
|
||||
this.parentChildType = parentChildType;
|
||||
|
@ -751,7 +752,8 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
|
|||
}
|
||||
}
|
||||
|
||||
static InnerHitBuilder rewrite(InnerHitBuilder original, QueryBuilder rewrittenQuery) {
|
||||
// TODO public for hasParent and hasChild query
|
||||
public static InnerHitBuilder rewrite(InnerHitBuilder original, QueryBuilder rewrittenQuery) {
|
||||
if (original == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.apache.lucene.search.MatchNoDocsQuery;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.BitSetProducer;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -36,6 +35,7 @@ import org.elasticsearch.index.search.ESToParentBlockJoinQuery;
|
|||
import org.elasticsearch.index.search.NestedHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -144,7 +144,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
builder.field(PATH_FIELD.getPreferredName(), path);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
if (scoreMode != null) {
|
||||
builder.field(SCORE_MODE_FIELD.getPreferredName(), HasChildQueryBuilder.scoreModeAsString(scoreMode));
|
||||
builder.field(SCORE_MODE_FIELD.getPreferredName(), scoreModeAsString(scoreMode));
|
||||
}
|
||||
printBoostAndQueryName(builder);
|
||||
if (innerHitBuilder != null) {
|
||||
|
@ -183,7 +183,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
} else if (IGNORE_UNMAPPED_FIELD.match(currentFieldName)) {
|
||||
ignoreUnmapped = parser.booleanValue();
|
||||
} else if (SCORE_MODE_FIELD.match(currentFieldName)) {
|
||||
scoreMode = HasChildQueryBuilder.parseScoreMode(parser.text());
|
||||
scoreMode = parseScoreMode(parser.text());
|
||||
} else if (AbstractQueryBuilder.NAME_FIELD.match(currentFieldName)) {
|
||||
queryName = parser.text();
|
||||
} else {
|
||||
|
@ -201,6 +201,30 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
return queryBuilder;
|
||||
}
|
||||
|
||||
public static ScoreMode parseScoreMode(String scoreModeString) {
|
||||
if ("none".equals(scoreModeString)) {
|
||||
return ScoreMode.None;
|
||||
} else if ("min".equals(scoreModeString)) {
|
||||
return ScoreMode.Min;
|
||||
} else if ("max".equals(scoreModeString)) {
|
||||
return ScoreMode.Max;
|
||||
} else if ("avg".equals(scoreModeString)) {
|
||||
return ScoreMode.Avg;
|
||||
} else if ("sum".equals(scoreModeString)) {
|
||||
return ScoreMode.Total;
|
||||
}
|
||||
throw new IllegalArgumentException("No score mode for child query [" + scoreModeString + "] found");
|
||||
}
|
||||
|
||||
public static String scoreModeAsString(ScoreMode scoreMode) {
|
||||
if (scoreMode == ScoreMode.Total) {
|
||||
// Lucene uses 'total' but 'sum' is more consistent with other elasticsearch APIs
|
||||
return "sum";
|
||||
} else {
|
||||
return scoreMode.name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getWriteableName() {
|
||||
return NAME;
|
||||
|
|
|
@ -471,30 +471,6 @@ public abstract class QueryBuilders {
|
|||
return moreLikeThisQuery(null, null, likeItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new has_child query, with the child type and the query to run on the child documents. The
|
||||
* results of this query are the parent docs that those child docs matched.
|
||||
*
|
||||
* @param type The child type.
|
||||
* @param query The query.
|
||||
* @param scoreMode How the scores from the children hits should be aggregated into the parent hit.
|
||||
*/
|
||||
public static HasChildQueryBuilder hasChildQuery(String type, QueryBuilder query, ScoreMode scoreMode) {
|
||||
return new HasChildQueryBuilder(type, query, scoreMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parent query, with the parent type and the query to run on the parent documents. The
|
||||
* results of this query are the children docs that those parent docs matched.
|
||||
*
|
||||
* @param type The parent type.
|
||||
* @param query The query.
|
||||
* @param score Whether the score from the parent hit should propagate to the child hit
|
||||
*/
|
||||
public static HasParentQueryBuilder hasParentQuery(String type, QueryBuilder query, boolean score) {
|
||||
return new HasParentQueryBuilder(type, query, score);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parent id query that returns all child documents of the specified type that
|
||||
* point to the specified id.
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
package org.elasticsearch.search;
|
||||
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.NamedRegistry;
|
||||
import org.elasticsearch.common.geo.ShapesAvailability;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilders;
|
||||
|
@ -45,8 +43,6 @@ import org.elasticsearch.index.query.GeoBoundingBoxQueryBuilder;
|
|||
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
|
||||
import org.elasticsearch.index.query.GeoPolygonQueryBuilder;
|
||||
import org.elasticsearch.index.query.GeoShapeQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchNoneQueryBuilder;
|
||||
|
@ -103,8 +99,6 @@ import org.elasticsearch.search.aggregations.InternalAggregation;
|
|||
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.adjacency.InternalAdjacencyMatrix;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.ChildrenAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.InternalChildren;
|
||||
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
|
||||
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregationBuilder;
|
||||
|
@ -256,7 +250,6 @@ import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -410,9 +403,6 @@ public class SearchModule {
|
|||
GeoCentroidAggregationBuilder::parse).addResultReader(InternalGeoCentroid::new));
|
||||
registerAggregation(new AggregationSpec(ScriptedMetricAggregationBuilder.NAME, ScriptedMetricAggregationBuilder::new,
|
||||
ScriptedMetricAggregationBuilder::parse).addResultReader(InternalScriptedMetric::new));
|
||||
registerAggregation(new AggregationSpec(ChildrenAggregationBuilder.NAME, ChildrenAggregationBuilder::new,
|
||||
ChildrenAggregationBuilder::parse).addResultReader(InternalChildren::new));
|
||||
|
||||
registerFromPlugin(plugins, SearchPlugin::getAggregations, this::registerAggregation);
|
||||
}
|
||||
|
||||
|
@ -706,8 +696,6 @@ public class SearchModule {
|
|||
MatchPhrasePrefixQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(MultiMatchQueryBuilder.NAME, MultiMatchQueryBuilder::new, MultiMatchQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(NestedQueryBuilder.NAME, NestedQueryBuilder::new, NestedQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(HasChildQueryBuilder.NAME, HasChildQueryBuilder::new, HasChildQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(HasParentQueryBuilder.NAME, HasParentQueryBuilder::new, HasParentQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(DisMaxQueryBuilder.NAME, DisMaxQueryBuilder::new, DisMaxQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(IdsQueryBuilder.NAME, IdsQueryBuilder::new, IdsQueryBuilder::fromXContent));
|
||||
registerQuery(new QuerySpec<>(MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new, MatchAllQueryBuilder::fromXContent));
|
||||
|
|
|
@ -23,8 +23,6 @@ import org.elasticsearch.common.geo.GeoPoint;
|
|||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrix;
|
||||
import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.Children;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.ChildrenAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
|
||||
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.filters.Filters;
|
||||
|
@ -163,20 +161,20 @@ public class AggregationBuilders {
|
|||
public static FiltersAggregationBuilder filters(String name, QueryBuilder... filters) {
|
||||
return new FiltersAggregationBuilder(name, filters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link AdjacencyMatrix} aggregation with the given name.
|
||||
*/
|
||||
public static AdjacencyMatrixAggregationBuilder adjacencyMatrix(String name, Map<String, QueryBuilder> filters) {
|
||||
return new AdjacencyMatrixAggregationBuilder(name, filters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AdjacencyMatrix} aggregation with the given name and separator
|
||||
*/
|
||||
public static AdjacencyMatrixAggregationBuilder adjacencyMatrix(String name, String separator, Map<String, QueryBuilder> filters) {
|
||||
return new AdjacencyMatrixAggregationBuilder(name, separator, filters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Sampler} aggregation with the given name.
|
||||
|
@ -220,13 +218,6 @@ public class AggregationBuilders {
|
|||
return new ReverseNestedAggregationBuilder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Children} aggregation with the given name.
|
||||
*/
|
||||
public static ChildrenAggregationBuilder children(String name, String childType) {
|
||||
return new ChildrenAggregationBuilder(name, childType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link GeoDistance} aggregation with the given name.
|
||||
*/
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.apache.lucene.search.highlight.WeightedSpanTerm;
|
|||
import org.apache.lucene.search.highlight.WeightedSpanTermExtractor;
|
||||
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
|
||||
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
@ -83,7 +82,7 @@ public final class CustomQueryScorer extends QueryScorer {
|
|||
}
|
||||
|
||||
protected void extract(Query query, float boost, Map<String, WeightedSpanTerm> terms) throws IOException {
|
||||
if (query instanceof HasChildQueryBuilder.LateParsingQuery) {
|
||||
if (isChildOrParentQuery(query.getClass())) {
|
||||
// skip has_child or has_parent queries, see: https://github.com/elastic/elasticsearch/issues/14999
|
||||
return;
|
||||
} else if (query instanceof FunctionScoreQuery) {
|
||||
|
@ -94,5 +93,13 @@ public final class CustomQueryScorer extends QueryScorer {
|
|||
super.extract(query, boost, terms);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround to detect parent/child query
|
||||
*/
|
||||
private static final String PARENT_CHILD_QUERY_NAME = "HasChildQueryBuilder$LateParsingQuery";
|
||||
private static boolean isChildOrParentQuery(Class<?> clazz) {
|
||||
return clazz.getName().endsWith(PARENT_CHILD_QUERY_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,156 +450,7 @@ public class BulkWithUpdatesIT extends ESIntegTestCase {
|
|||
assertHitCount(countResponse, numDocs);
|
||||
}
|
||||
|
||||
/*
|
||||
Test for https://github.com/elastic/elasticsearch/issues/3444
|
||||
*/
|
||||
public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
|
||||
client().admin().indices().prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
|
||||
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON)
|
||||
.execute().actionGet();
|
||||
ensureGreen();
|
||||
|
||||
BulkRequestBuilder builder = client().prepareBulk();
|
||||
|
||||
// It's important to use JSON parsing here and request objects: issue 3444 is related to incomplete option parsing
|
||||
byte[] addParent = new BytesArray(
|
||||
"{" +
|
||||
" \"index\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"parent\"," +
|
||||
" \"_id\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"doc\" : {" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
" }," +
|
||||
" \"doc_as_upsert\" : \"true\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
builder.add(addParent, 0, addParent.length, XContentType.JSON);
|
||||
builder.add(addChild, 0, addChild.length, XContentType.JSON);
|
||||
|
||||
BulkResponse bulkResponse = builder.get();
|
||||
assertThat(bulkResponse.getItems().length, equalTo(2));
|
||||
assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
|
||||
|
||||
client().admin().indices().prepareRefresh("test").get();
|
||||
|
||||
//we check that the _parent field was set on the child document by using the has parent query
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(QueryBuilders.hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(searchResponse);
|
||||
assertSearchHits(searchResponse, "child1");
|
||||
}
|
||||
|
||||
/*
|
||||
Test for https://github.com/elastic/elasticsearch/issues/3444
|
||||
*/
|
||||
public void testBulkUpdateUpsertWithParent() throws Exception {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
|
||||
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
|
||||
ensureGreen();
|
||||
|
||||
BulkRequestBuilder builder = client().prepareBulk();
|
||||
|
||||
byte[] addParent = new BytesArray(
|
||||
"{" +
|
||||
" \"index\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"parent\"," +
|
||||
" \"_id\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild1 = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"script\" : {" +
|
||||
" \"inline\" : \"ctx._source.field2 = 'value2'\"" +
|
||||
" }," +
|
||||
" \"lang\" : \"" + CustomScriptPlugin.NAME + "\"," +
|
||||
" \"upsert\" : {" +
|
||||
" \"field1\" : \"value1'\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild2 = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"script\" : \"ctx._source.field2 = 'value2'\"," +
|
||||
" \"upsert\" : {" +
|
||||
" \"field1\" : \"value1'\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
builder.add(addParent, 0, addParent.length, XContentType.JSON);
|
||||
builder.add(addChild1, 0, addChild1.length, XContentType.JSON);
|
||||
builder.add(addChild2, 0, addChild2.length, XContentType.JSON);
|
||||
|
||||
BulkResponse bulkResponse = builder.get();
|
||||
assertThat(bulkResponse.getItems().length, equalTo(3));
|
||||
assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[2].isFailed(), equalTo(true));
|
||||
assertThat(bulkResponse.getItems()[2].getFailure().getCause().getCause().getMessage(),
|
||||
equalTo("script_lang not supported [painless]"));
|
||||
|
||||
client().admin().indices().prepareRefresh("test").get();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(QueryBuilders.hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
|
||||
.get();
|
||||
|
||||
assertSearchHits(searchResponse, "child1");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for https://github.com/elastic/elasticsearch/issues/8365
|
||||
|
|
|
@ -63,8 +63,6 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_BLOCKS_ME
|
|||
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_BLOCKS_READ;
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_BLOCKS_WRITE;
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_READ_ONLY;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
|
@ -824,27 +822,6 @@ public class IndexAliasesIT extends ESIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testAliasesFilterWithHasChildQuery() throws Exception {
|
||||
assertAcked(prepareCreate("my-index")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent")
|
||||
.addMapping("child", "_parent", "type=parent")
|
||||
);
|
||||
client().prepareIndex("my-index", "parent", "1").setSource("{}", XContentType.JSON).get();
|
||||
client().prepareIndex("my-index", "child", "2").setSource("{}", XContentType.JSON).setParent("1").get();
|
||||
refresh();
|
||||
|
||||
assertAcked(admin().indices().prepareAliases().addAlias("my-index", "filter1", hasChildQuery("child", matchAllQuery(), ScoreMode.None)));
|
||||
assertAcked(admin().indices().prepareAliases().addAlias("my-index", "filter2", hasParentQuery("parent", matchAllQuery(), false)));
|
||||
|
||||
SearchResponse response = client().prepareSearch("filter1").get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
response = client().prepareSearch("filter2").get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
}
|
||||
|
||||
public void testAliasesWithBlocks() {
|
||||
createIndex("test");
|
||||
ensureGreen();
|
||||
|
|
|
@ -153,24 +153,6 @@ public class InnerHitBuilderTests extends ESTestCase {
|
|||
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
|
||||
}
|
||||
|
||||
public void testInlineLeafInnerHitsHasChildQuery() throws Exception {
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
.innerHit(leafInnerHits, false);
|
||||
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
|
||||
hasChildQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
|
||||
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
|
||||
}
|
||||
|
||||
public void testInlineLeafInnerHitsHasParentQuery() throws Exception {
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
HasParentQueryBuilder hasParentQueryBuilder = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
|
||||
.innerHit(leafInnerHits, false);
|
||||
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
|
||||
hasParentQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
|
||||
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
|
||||
}
|
||||
|
||||
public void testInlineLeafInnerHitsNestedQueryViaBoolQuery() {
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
|
@ -181,25 +163,6 @@ public class InnerHitBuilderTests extends ESTestCase {
|
|||
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
|
||||
}
|
||||
|
||||
public void testInlineLeafInnerHitsNestedQueryViaDisMaxQuery() {
|
||||
InnerHitBuilder leafInnerHits1 = randomInnerHits();
|
||||
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
.innerHit(leafInnerHits1, false);
|
||||
|
||||
InnerHitBuilder leafInnerHits2 = randomInnerHits();
|
||||
HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
.innerHit(leafInnerHits2, false);
|
||||
|
||||
DisMaxQueryBuilder disMaxQueryBuilder = new DisMaxQueryBuilder();
|
||||
disMaxQueryBuilder.add(nestedQueryBuilder);
|
||||
disMaxQueryBuilder.add(hasChildQueryBuilder);
|
||||
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
|
||||
disMaxQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
|
||||
assertThat(innerHitBuilders.size(), equalTo(2));
|
||||
assertThat(innerHitBuilders.get(leafInnerHits1.getName()), notNullValue());
|
||||
assertThat(innerHitBuilders.get(leafInnerHits2.getName()), notNullValue());
|
||||
}
|
||||
|
||||
public void testInlineLeafInnerHitsNestedQueryViaConstantScoreQuery() {
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
|
@ -252,43 +215,6 @@ public class InnerHitBuilderTests extends ESTestCase {
|
|||
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
|
||||
}
|
||||
|
||||
public void testBuild_ignoreUnmappedHasChildQuery() throws Exception {
|
||||
QueryShardContext queryShardContext = mock(QueryShardContext.class);
|
||||
when(queryShardContext.documentMapper("type")).thenReturn(null);
|
||||
SearchContext searchContext = mock(SearchContext.class);
|
||||
when(searchContext.getQueryShardContext()).thenReturn(queryShardContext);
|
||||
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
HasChildQueryBuilder query1 = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
.innerHit(leafInnerHits, false);
|
||||
expectThrows(IllegalStateException.class, () -> query1.innerHit().build(searchContext, new InnerHitsContext()));
|
||||
|
||||
HasChildQueryBuilder query2 = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
|
||||
.innerHit(leafInnerHits, true);
|
||||
InnerHitsContext innerHitsContext = new InnerHitsContext();
|
||||
query2.innerHit().build(searchContext, innerHitsContext);
|
||||
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
|
||||
}
|
||||
|
||||
public void testBuild_ingoreUnmappedHasParentQuery() throws Exception {
|
||||
QueryShardContext queryShardContext = mock(QueryShardContext.class);
|
||||
when(queryShardContext.documentMapper("type")).thenReturn(null);
|
||||
SearchContext searchContext = mock(SearchContext.class);
|
||||
when(searchContext.getQueryShardContext()).thenReturn(queryShardContext);
|
||||
|
||||
InnerHitBuilder leafInnerHits = randomInnerHits();
|
||||
HasParentQueryBuilder query1 = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
|
||||
.innerHit(leafInnerHits, false);
|
||||
expectThrows(IllegalStateException.class, () -> query1.innerHit().build(searchContext, new InnerHitsContext()));
|
||||
|
||||
HasParentQueryBuilder query2 = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
|
||||
.innerHit(leafInnerHits, true);
|
||||
InnerHitsContext innerHitsContext = new InnerHitsContext();
|
||||
query2.innerHit().build(searchContext, innerHitsContext);
|
||||
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
|
||||
}
|
||||
|
||||
|
||||
public static InnerHitBuilder randomInnerHits() {
|
||||
return randomInnerHits(true, true);
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
|
|||
}
|
||||
|
||||
/**
|
||||
* @return a {@link HasChildQueryBuilder} with random values all over the place
|
||||
* @return a {@link NestedQueryBuilder} with random values all over the place
|
||||
*/
|
||||
@Override
|
||||
protected NestedQueryBuilder doCreateTestQueryBuilder() {
|
||||
|
@ -203,4 +203,46 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
|
|||
assertThat(query, notNullValue());
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
}
|
||||
|
||||
public void testMinFromString() {
|
||||
assertThat("fromString(min) != MIN", ScoreMode.Min, equalTo(NestedQueryBuilder.parseScoreMode("min")));
|
||||
assertThat("min", equalTo(NestedQueryBuilder.scoreModeAsString(ScoreMode.Min)));
|
||||
}
|
||||
|
||||
public void testMaxFromString() {
|
||||
assertThat("fromString(max) != MAX", ScoreMode.Max, equalTo(NestedQueryBuilder.parseScoreMode("max")));
|
||||
assertThat("max", equalTo(NestedQueryBuilder.scoreModeAsString(ScoreMode.Max)));
|
||||
}
|
||||
|
||||
public void testAvgFromString() {
|
||||
assertThat("fromString(avg) != AVG", ScoreMode.Avg, equalTo(NestedQueryBuilder.parseScoreMode("avg")));
|
||||
assertThat("avg", equalTo(NestedQueryBuilder.scoreModeAsString(ScoreMode.Avg)));
|
||||
}
|
||||
|
||||
public void testSumFromString() {
|
||||
assertThat("fromString(total) != SUM", ScoreMode.Total, equalTo(NestedQueryBuilder.parseScoreMode("sum")));
|
||||
assertThat("sum", equalTo(NestedQueryBuilder.scoreModeAsString(ScoreMode.Total)));
|
||||
}
|
||||
|
||||
public void testNoneFromString() {
|
||||
assertThat("fromString(none) != NONE", ScoreMode.None, equalTo(NestedQueryBuilder.parseScoreMode("none")));
|
||||
assertThat("none", equalTo(NestedQueryBuilder.scoreModeAsString(ScoreMode.None)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should throw {@link IllegalArgumentException} instead of NPE.
|
||||
*/
|
||||
public void testThatNullFromStringThrowsException() {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> NestedQueryBuilder.parseScoreMode(null));
|
||||
assertEquals("No score mode for child query [null] found", e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure should not change (and the value should never match anything...).
|
||||
*/
|
||||
public void testThatUnrecognizedFromStringThrowsException() {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> NestedQueryBuilder.parseScoreMode("unrecognized value"));
|
||||
assertEquals("No score mode for child query [unrecognized value] found", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,8 +270,6 @@ public class SearchModuleTests extends ModuleTestCase {
|
|||
"geo_distance",
|
||||
"geo_polygon",
|
||||
"geo_shape",
|
||||
"has_child",
|
||||
"has_parent",
|
||||
"ids",
|
||||
"match",
|
||||
"match_all",
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.search.aggregations.bucket.filter;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.search.aggregations.bucket.global;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.search.aggregations.bucket.missing;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.search.aggregations.bucket.nested;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.search.aggregations.bucket.nested;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.elasticsearch.search.aggregations.bucket.sampler;
|
|||
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -42,4 +42,4 @@ public class InternalSamplerTests extends InternalSingleBucketAggregationTestCas
|
|||
protected Writeable.Reader<InternalSampler> instanceReader() {
|
||||
return InternalSampler::new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,8 +55,6 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
|||
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
|
||||
|
@ -246,268 +244,6 @@ public class InnerHitsIT extends ESIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testSimpleParentChild() throws Exception {
|
||||
assertAcked(prepareCreate("articles")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("article", "title", "type=text")
|
||||
.addMapping("comment", "_parent", "type=article", "message", "type=text,fielddata=true")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("articles", "article", "1").setSource("title", "quick brown fox"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "1").setParent("1").setSource("message", "fox eat quick"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "2").setParent("1").setSource("message", "fox ate rabbit x y z"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "3").setParent("1").setSource("message", "rabbit got away"));
|
||||
requests.add(client().prepareIndex("articles", "article", "2").setSource("title", "big gray elephant"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "4").setParent("2").setSource("message", "elephant captured"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "5").setParent("2").setSource("message", "mice squashed by elephant x"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "6").setParent("2").setSource("message", "elephant scared by mice x y"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("1"));
|
||||
assertThat(response.getHits().getAt(0).getShard(), notNullValue());
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(2L));
|
||||
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(1).getType(), equalTo("comment"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment", matchQuery("message", "elephant"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("2"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(3L));
|
||||
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("4"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("5"));
|
||||
assertThat(innerHits.getAt(1).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(2).getId(), equalTo("6"));
|
||||
assertThat(innerHits.getAt(2).getType(), equalTo("comment"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(
|
||||
hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None).innerHit(
|
||||
new InnerHitBuilder()
|
||||
.addDocValueField("message")
|
||||
.setHighlightBuilder(new HighlightBuilder().field("message"))
|
||||
.setExplain(true).setSize(1)
|
||||
.addScriptField("script", new Script(ScriptType.INLINE, MockScriptEngine.NAME, "5",
|
||||
Collections.emptyMap())),
|
||||
false)
|
||||
).get();
|
||||
assertNoFailures(response);
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getHits().length, equalTo(1));
|
||||
assertThat(innerHits.getAt(0).getHighlightFields().get("message").getFragments()[0].string(), equalTo("<em>fox</em> eat quick"));
|
||||
assertThat(innerHits.getAt(0).getExplanation().toString(), containsString("weight(message:fox"));
|
||||
assertThat(innerHits.getAt(0).getFields().get("message").getValue().toString(), equalTo("eat"));
|
||||
assertThat(innerHits.getAt(0).getFields().get("script").getValue().toString(), equalTo("5"));
|
||||
}
|
||||
|
||||
public void testRandomParentChild() throws Exception {
|
||||
assertAcked(prepareCreate("idx")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent")
|
||||
.addMapping("child1", "_parent", "type=parent")
|
||||
.addMapping("child2", "_parent", "type=parent")
|
||||
);
|
||||
int numDocs = scaledRandomIntBetween(5, 50);
|
||||
List<IndexRequestBuilder> requestBuilders = new ArrayList<>();
|
||||
|
||||
int child1 = 0;
|
||||
int child2 = 0;
|
||||
int[] child1InnerObjects = new int[numDocs];
|
||||
int[] child2InnerObjects = new int[numDocs];
|
||||
for (int parent = 0; parent < numDocs; parent++) {
|
||||
String parentId = String.format(Locale.ENGLISH, "%03d", parent);
|
||||
requestBuilders.add(client().prepareIndex("idx", "parent", parentId).setSource("{}", XContentType.JSON));
|
||||
|
||||
int numChildDocs = child1InnerObjects[parent] = scaledRandomIntBetween(1, numDocs);
|
||||
int limit = child1 + numChildDocs;
|
||||
for (; child1 < limit; child1++) {
|
||||
requestBuilders.add(client().prepareIndex("idx", "child1",
|
||||
String.format(Locale.ENGLISH, "%04d", child1)).setParent(parentId).setSource("{}", XContentType.JSON));
|
||||
}
|
||||
numChildDocs = child2InnerObjects[parent] = scaledRandomIntBetween(1, numDocs);
|
||||
limit = child2 + numChildDocs;
|
||||
for (; child2 < limit; child2++) {
|
||||
requestBuilders.add(client().prepareIndex("idx", "child2",
|
||||
String.format(Locale.ENGLISH, "%04d", child2)).setParent(parentId).setSource("{}", XContentType.JSON));
|
||||
}
|
||||
}
|
||||
indexRandom(true, requestBuilders);
|
||||
|
||||
int size = randomIntBetween(0, numDocs);
|
||||
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
|
||||
boolQuery.should(constantScoreQuery(hasChildQuery("child1", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("a")
|
||||
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
|
||||
boolQuery.should(constantScoreQuery(hasChildQuery("child2", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("b")
|
||||
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
|
||||
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||
.setSize(numDocs)
|
||||
.setTypes("parent")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(boolQuery)
|
||||
.get();
|
||||
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, numDocs);
|
||||
assertThat(searchResponse.getHits().getHits().length, equalTo(numDocs));
|
||||
|
||||
int offset1 = 0;
|
||||
int offset2 = 0;
|
||||
for (int parent = 0; parent < numDocs; parent++) {
|
||||
SearchHit searchHit = searchResponse.getHits().getAt(parent);
|
||||
assertThat(searchHit.getType(), equalTo("parent"));
|
||||
assertThat(searchHit.getId(), equalTo(String.format(Locale.ENGLISH, "%03d", parent)));
|
||||
assertThat(searchHit.getShard(), notNullValue());
|
||||
|
||||
SearchHits inner = searchHit.getInnerHits().get("a");
|
||||
assertThat(inner.getTotalHits(), equalTo((long) child1InnerObjects[parent]));
|
||||
for (int child = 0; child < child1InnerObjects[parent] && child < size; child++) {
|
||||
SearchHit innerHit = inner.getAt(child);
|
||||
assertThat(innerHit.getType(), equalTo("child1"));
|
||||
String childId = String.format(Locale.ENGLISH, "%04d", offset1 + child);
|
||||
assertThat(innerHit.getId(), equalTo(childId));
|
||||
assertThat(innerHit.getNestedIdentity(), nullValue());
|
||||
}
|
||||
offset1 += child1InnerObjects[parent];
|
||||
|
||||
inner = searchHit.getInnerHits().get("b");
|
||||
assertThat(inner.getTotalHits(), equalTo((long) child2InnerObjects[parent]));
|
||||
for (int child = 0; child < child2InnerObjects[parent] && child < size; child++) {
|
||||
SearchHit innerHit = inner.getAt(child);
|
||||
assertThat(innerHit.getType(), equalTo("child2"));
|
||||
String childId = String.format(Locale.ENGLISH, "%04d", offset2 + child);
|
||||
assertThat(innerHit.getId(), equalTo(childId));
|
||||
assertThat(innerHit.getNestedIdentity(), nullValue());
|
||||
}
|
||||
offset2 += child2InnerObjects[parent];
|
||||
}
|
||||
}
|
||||
|
||||
public void testInnerHitsOnHasParent() throws Exception {
|
||||
assertAcked(prepareCreate("stack")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("question", "body", "type=text")
|
||||
.addMapping("answer", "_parent", "type=question", "body", "type=text")
|
||||
);
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("stack", "question", "1").setSource("body", "I'm using HTTPS + Basic authentication "
|
||||
+ "to protect a resource. How can I throttle authentication attempts to protect against brute force attacks?"));
|
||||
requests.add(client().prepareIndex("stack", "answer", "1").setParent("1").setSource("body",
|
||||
"install fail2ban and enable rules for apache"));
|
||||
requests.add(client().prepareIndex("stack", "question", "2").setSource("body",
|
||||
"I have firewall rules set up and also denyhosts installed.\\ndo I also need to install fail2ban?"));
|
||||
requests.add(client().prepareIndex("stack", "answer", "2").setParent("2").setSource("body",
|
||||
"Denyhosts protects only ssh; Fail2Ban protects all daemons."));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("stack")
|
||||
.setTypes("answer")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(
|
||||
boolQuery()
|
||||
.must(matchQuery("body", "fail2ban"))
|
||||
.must(hasParentQuery("question", matchAllQuery(), false).innerHit(new InnerHitBuilder(), false))
|
||||
).get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
|
||||
SearchHit searchHit = response.getHits().getAt(0);
|
||||
assertThat(searchHit.getId(), equalTo("1"));
|
||||
assertThat(searchHit.getType(), equalTo("answer"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getTotalHits(), equalTo(1L));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getType(), equalTo("question"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getId(), equalTo("1"));
|
||||
|
||||
searchHit = response.getHits().getAt(1);
|
||||
assertThat(searchHit.getId(), equalTo("2"));
|
||||
assertThat(searchHit.getType(), equalTo("answer"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getTotalHits(), equalTo(1L));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getType(), equalTo("question"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getId(), equalTo("2"));
|
||||
}
|
||||
|
||||
public void testParentChildMultipleLayers() throws Exception {
|
||||
assertAcked(prepareCreate("articles")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("article", "title", "type=text")
|
||||
.addMapping("comment", "_parent", "type=article", "message", "type=text")
|
||||
.addMapping("remark", "_parent", "type=comment", "message", "type=text")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("articles", "article", "1").setSource("title", "quick brown fox"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "1").setParent("1").setSource("message", "fox eat quick"));
|
||||
requests.add(client().prepareIndex("articles", "remark", "1").setParent("1").setRouting("1").setSource("message", "good"));
|
||||
requests.add(client().prepareIndex("articles", "article", "2").setSource("title", "big gray elephant"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "2").setParent("2").setSource("message", "elephant captured"));
|
||||
requests.add(client().prepareIndex("articles", "remark", "2").setParent("2").setRouting("2").setSource("message", "bad"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment",
|
||||
hasChildQuery("remark", matchQuery("message", "good"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("1"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
|
||||
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("remark"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment",
|
||||
hasChildQuery("remark", matchQuery("message", "bad"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("2"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
|
||||
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("remark"));
|
||||
}
|
||||
|
||||
public void testNestedMultipleLayers() throws Exception {
|
||||
assertAcked(prepareCreate("articles").addMapping("article", jsonBuilder().startObject()
|
||||
.startObject("article").startObject("properties")
|
||||
|
@ -724,92 +460,6 @@ public class InnerHitsIT extends ESIntegTestCase {
|
|||
assertThat(messages.getAt(0).getNestedIdentity().getChild(), nullValue());
|
||||
}
|
||||
|
||||
public void testRoyals() throws Exception {
|
||||
assertAcked(
|
||||
prepareCreate("royals")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("king")
|
||||
.addMapping("prince", "_parent", "type=king")
|
||||
.addMapping("duke", "_parent", "type=prince")
|
||||
.addMapping("earl", "_parent", "type=duke")
|
||||
.addMapping("baron", "_parent", "type=earl")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("royals", "king", "king").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "prince", "prince").setParent("king").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "duke", "duke").setParent("prince").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl1").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl2").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl3").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl4").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron1").setParent("earl1").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron2").setParent("earl2").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron3").setParent("earl3").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron4").setParent("earl4").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("royals")
|
||||
.setTypes("duke")
|
||||
.setQuery(boolQuery()
|
||||
.filter(hasParentQuery("prince",
|
||||
hasParentQuery("king", matchAllQuery(), false).innerHit(new InnerHitBuilder().setName("kings"), false),
|
||||
false).innerHit(new InnerHitBuilder().setName("princes"), false)
|
||||
)
|
||||
.filter(hasChildQuery("earl",
|
||||
hasChildQuery("baron", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("barons"), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder()
|
||||
.addSort(SortBuilders.fieldSort("_uid").order(SortOrder.ASC))
|
||||
.setName("earls")
|
||||
.setSize(4), false)
|
||||
)
|
||||
)
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("duke"));
|
||||
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("earls");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(4L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("earl1"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("earl2"));
|
||||
assertThat(innerHits.getAt(2).getId(), equalTo("earl3"));
|
||||
assertThat(innerHits.getAt(3).getId(), equalTo("earl4"));
|
||||
|
||||
SearchHits innerInnerHits = innerHits.getAt(0).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron1"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(1).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron2"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(2).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron3"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(3).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron4"));
|
||||
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("princes");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("prince"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(0).getInnerHits().get("kings");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("king"));
|
||||
}
|
||||
|
||||
public void testMatchesQueriesNestedInnerHits() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.startObject("type1")
|
||||
|
@ -914,84 +564,6 @@ public class InnerHitsIT extends ESIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testMatchesQueriesParentChildInnerHits() throws Exception {
|
||||
assertAcked(prepareCreate("index")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child", "_parent", "type=parent"));
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("index", "parent", "1").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index", "child", "1").setParent("1").setSource("field", "value1"));
|
||||
requests.add(client().prepareIndex("index", "child", "2").setParent("1").setSource("field", "value2"));
|
||||
requests.add(client().prepareIndex("index", "parent", "2").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index", "child", "3").setParent("2").setSource("field", "value1"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("index")
|
||||
.setQuery(hasChildQuery("child", matchQuery("field", "value1").queryName("_name1"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.get();
|
||||
assertHitCount(response, 2);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name1"));
|
||||
|
||||
assertThat(response.getHits().getAt(1).getId(), equalTo("2"));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name1"));
|
||||
|
||||
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value2").queryName("_name2"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false);
|
||||
response = client().prepareSearch("index")
|
||||
.setQuery(query)
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name2"));
|
||||
}
|
||||
|
||||
public void testDontExplode() throws Exception {
|
||||
assertAcked(prepareCreate("index1")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child", "_parent", "type=parent"));
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("index1", "parent", "1").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index1", "child", "1").setParent("1").setSource("field", "value1"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value1"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
|
||||
SearchResponse response = client().prepareSearch("index1")
|
||||
.setQuery(query)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
|
||||
assertAcked(prepareCreate("index2").addMapping("type", "nested", "type=nested"));
|
||||
client().prepareIndex("index2", "type", "1").setSource(jsonBuilder().startObject()
|
||||
.startArray("nested")
|
||||
.startObject()
|
||||
.field("field", "value1")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject())
|
||||
.setRefreshPolicy(IMMEDIATE)
|
||||
.get();
|
||||
|
||||
query = nestedQuery("nested", matchQuery("nested.field", "value1"), ScoreMode.Avg)
|
||||
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
|
||||
response = client().prepareSearch("index2")
|
||||
.setQuery(query)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
}
|
||||
|
||||
public void testNestedSourceFiltering() throws Exception {
|
||||
assertAcked(prepareCreate("index1").addMapping("message", "comments", "type=nested"));
|
||||
client().prepareIndex("index1", "message", "1").setSource(jsonBuilder().startObject()
|
||||
|
@ -1021,25 +593,6 @@ public class InnerHitsIT extends ESIntegTestCase {
|
|||
equalTo("fox ate rabbit x y z"));
|
||||
}
|
||||
|
||||
public void testNestedInnerHitWrappedInParentChildInnerhit() throws Exception {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child_type", "_parent", "type=parent_type", "nested_type", "type=nested"));
|
||||
client().prepareIndex("test", "parent_type", "1").setSource("key", "value").get();
|
||||
client().prepareIndex("test", "child_type", "2").setParent("1").setSource("nested_type", Collections.singletonMap("key", "value"))
|
||||
.get();
|
||||
refresh();
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchQuery("key", "value"))
|
||||
.should(hasChildQuery("child_type", nestedQuery("nested_type", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false), ScoreMode.None).innerHit(new InnerHitBuilder(), false)))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
SearchHit hit = response.getHits().getAt(0);
|
||||
assertThat(hit.getInnerHits().get("child_type").getAt(0).field("_parent").getValue(), equalTo("1"));
|
||||
assertThat(hit.getInnerHits().get("child_type").getAt(0).getInnerHits().get("nested_type").getAt(0).field("_parent"), nullValue());
|
||||
}
|
||||
|
||||
public void testInnerHitsWithIgnoreUnmapped() throws Exception {
|
||||
assertAcked(prepareCreate("index1")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
|
@ -1062,17 +615,6 @@ public class InnerHitsIT extends ESIntegTestCase {
|
|||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
assertSearchHits(response, "1", "3");
|
||||
|
||||
response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(boolQuery()
|
||||
.should(hasChildQuery("child_type", matchAllQuery(), ScoreMode.None).ignoreUnmapped(true)
|
||||
.innerHit(new InnerHitBuilder(), true))
|
||||
.should(termQuery("key", "value"))
|
||||
)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
assertSearchHits(response, "1", "3");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Import Aggregation definition classes:
|
|||
|
||||
[source,java]
|
||||
--------------------------------------------------
|
||||
import org.elasticsearch.search.aggregations.bucket.children.Children;
|
||||
import org.elasticsearch.join.aggregations.Children;
|
||||
--------------------------------------------------
|
||||
|
||||
[source,java]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
esplugin {
|
||||
description 'This module adds the support parent-child queries and aggregations'
|
||||
classname 'org.elasticsearch.join.ParentJoinPlugin'
|
||||
hasClientJar = true
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.join;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.join.aggregations.ChildrenAggregationBuilder;
|
||||
import org.elasticsearch.join.aggregations.InternalChildren;
|
||||
import org.elasticsearch.join.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.join.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.plugins.SearchPlugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ParentJoinPlugin extends Plugin implements SearchPlugin {
|
||||
public ParentJoinPlugin(Settings settings) {}
|
||||
|
||||
@Override
|
||||
public List<QuerySpec<?>> getQueries() {
|
||||
return Arrays.asList(
|
||||
new QuerySpec<>(HasChildQueryBuilder.NAME, HasChildQueryBuilder::new, HasChildQueryBuilder::fromXContent),
|
||||
new QuerySpec<>(HasParentQueryBuilder.NAME, HasParentQueryBuilder::new, HasParentQueryBuilder::fromXContent)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AggregationSpec> getAggregations() {
|
||||
return Collections.singletonList(
|
||||
new AggregationSpec(ChildrenAggregationBuilder.NAME, ChildrenAggregationBuilder::new, ChildrenAggregationBuilder::parse)
|
||||
.addResultReader(InternalChildren::new)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.elasticsearch.search.aggregations.bucket.SingleBucketAggregation;
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.ParsingException;
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.search.aggregations.Aggregator;
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
public abstract class JoinAggregationBuilders {
|
||||
/**
|
||||
* Create a new {@link Children} aggregation with the given name.
|
||||
*/
|
||||
public static ChildrenAggregationBuilder children(String name, String childType) {
|
||||
return new ChildrenAggregationBuilder(name, childType);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.elasticsearch.index.query;
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
|
@ -38,6 +38,14 @@ import org.elasticsearch.index.fielddata.IndexParentChildFieldData;
|
|||
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.ParentFieldMapper;
|
||||
import org.elasticsearch.index.query.AbstractQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.NestedQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryRewriteContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
@ -210,7 +218,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
builder.field(QUERY_FIELD.getPreferredName());
|
||||
query.toXContent(builder, params);
|
||||
builder.field(TYPE_FIELD.getPreferredName(), type);
|
||||
builder.field(SCORE_MODE_FIELD.getPreferredName(), scoreModeAsString(scoreMode));
|
||||
builder.field(SCORE_MODE_FIELD.getPreferredName(), NestedQueryBuilder.scoreModeAsString(scoreMode));
|
||||
builder.field(MIN_CHILDREN_FIELD.getPreferredName(), minChildren);
|
||||
builder.field(MAX_CHILDREN_FIELD.getPreferredName(), maxChildren);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
|
@ -251,7 +259,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
if (TYPE_FIELD.match(currentFieldName)) {
|
||||
childType = parser.text();
|
||||
} else if (SCORE_MODE_FIELD.match(currentFieldName)) {
|
||||
scoreMode = parseScoreMode(parser.text());
|
||||
scoreMode = NestedQueryBuilder.parseScoreMode(parser.text());
|
||||
} else if (AbstractQueryBuilder.BOOST_FIELD.match(currentFieldName)) {
|
||||
boost = parser.floatValue();
|
||||
} else if (MIN_CHILDREN_FIELD.match(currentFieldName)) {
|
||||
|
@ -278,30 +286,6 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
return hasChildQueryBuilder;
|
||||
}
|
||||
|
||||
public static ScoreMode parseScoreMode(String scoreModeString) {
|
||||
if ("none".equals(scoreModeString)) {
|
||||
return ScoreMode.None;
|
||||
} else if ("min".equals(scoreModeString)) {
|
||||
return ScoreMode.Min;
|
||||
} else if ("max".equals(scoreModeString)) {
|
||||
return ScoreMode.Max;
|
||||
} else if ("avg".equals(scoreModeString)) {
|
||||
return ScoreMode.Avg;
|
||||
} else if ("sum".equals(scoreModeString)) {
|
||||
return ScoreMode.Total;
|
||||
}
|
||||
throw new IllegalArgumentException("No score mode for child query [" + scoreModeString + "] found");
|
||||
}
|
||||
|
||||
public static String scoreModeAsString(ScoreMode scoreMode) {
|
||||
if (scoreMode == ScoreMode.Total) {
|
||||
// Lucene uses 'total' but 'sum' is more consistent with other elasticsearch APIs
|
||||
return "sum";
|
||||
} else {
|
||||
return scoreMode.name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
return NAME;
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.elasticsearch.index.query;
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
@ -33,6 +33,13 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.ParentFieldMapper;
|
||||
import org.elasticsearch.index.query.AbstractQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryRewriteContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
public abstract class JoinQueryBuilders {
|
||||
/**
|
||||
* Constructs a new has_child query, with the child type and the query to run on the child documents. The
|
||||
* results of this query are the parent docs that those child docs matched.
|
||||
*
|
||||
* @param type The child type.
|
||||
* @param query The query.
|
||||
* @param scoreMode How the scores from the children hits should be aggregated into the parent hit.
|
||||
*/
|
||||
public static HasChildQueryBuilder hasChildQuery(String type, QueryBuilder query, ScoreMode scoreMode) {
|
||||
return new HasChildQueryBuilder(type, query, scoreMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parent query, with the parent type and the query to run on the parent documents. The
|
||||
* results of this query are the children docs that those parent docs matched.
|
||||
*
|
||||
* @param type The parent type.
|
||||
* @param query The query.
|
||||
* @param score Whether the score from the parent hit should propagate to the child hit
|
||||
*/
|
||||
public static HasParentQueryBuilder hasParentQuery(String type, QueryBuilder query, boolean score) {
|
||||
return new HasParentQueryBuilder(type, query, score);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.join;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
|
||||
public class ParentChildClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
public ParentChildClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws Exception {
|
||||
return createParameters();
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.elasticsearch.search.aggregations.bucket;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
|
@ -26,27 +26,33 @@ import org.elasticsearch.client.Requests;
|
|||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.Children;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
||||
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
|
||||
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.ESIntegTestCase.Scope;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.children;
|
||||
import static org.elasticsearch.join.aggregations.JoinAggregationBuilders.children;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.topHits;
|
||||
|
@ -59,13 +65,28 @@ import static org.hamcrest.Matchers.greaterThan;
|
|||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
|
||||
@ESIntegTestCase.SuiteScopeTestCase
|
||||
@ClusterScope(scope = Scope.SUITE)
|
||||
public class ChildrenIT extends ESIntegTestCase {
|
||||
|
||||
private static final Map<String, Control> categoryToControl = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setupSuiteScopeCluster() throws Exception {
|
||||
protected boolean ignoreExternalCluster() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return Collections.singleton(ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
|
||||
return nodePlugins();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupCluster() throws Exception {
|
||||
categoryToControl.clear();
|
||||
assertAcked(
|
||||
prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
|
@ -95,7 +116,8 @@ public class ChildrenIT extends ESIntegTestCase {
|
|||
control.articleIds.add(id);
|
||||
}
|
||||
|
||||
requests.add(client().prepareIndex("test", "article", id).setCreate(true).setSource("category", categories, "randomized", true));
|
||||
requests.add(client()
|
||||
.prepareIndex("test", "article", id).setCreate(true).setSource("category", categories, "randomized", true));
|
||||
}
|
||||
|
||||
String[] commenters = new String[randomIntBetween(5, 50)];
|
||||
|
@ -116,17 +138,24 @@ public class ChildrenIT extends ESIntegTestCase {
|
|||
control.commenterToCommentId.put(commenter, ids = new HashSet<>());
|
||||
}
|
||||
ids.add(idValue);
|
||||
requests.add(client().prepareIndex("test", "comment", idValue).setCreate(true).setParent(articleId).setSource("commenter", commenter));
|
||||
requests.add(client().prepareIndex("test", "comment", idValue)
|
||||
.setCreate(true).setParent(articleId).setSource("commenter", commenter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requests.add(client().prepareIndex("test", "article", "a").setSource("category", new String[]{"a"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "b").setSource("category", new String[]{"a", "b"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "c").setSource("category", new String[]{"a", "b", "c"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "d").setSource("category", new String[]{"c"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "comment", "a").setParent("a").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("test", "comment", "c").setParent("c").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("test", "article", "a")
|
||||
.setSource("category", new String[]{"a"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "b")
|
||||
.setSource("category", new String[]{"a", "b"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "c")
|
||||
.setSource("category", new String[]{"a", "b", "c"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "article", "d")
|
||||
.setSource("category", new String[]{"c"}, "randomized", false));
|
||||
requests.add(client().prepareIndex("test", "comment", "a")
|
||||
.setParent("a").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("test", "comment", "c")
|
||||
.setParent("c").setSource("{}", XContentType.JSON));
|
||||
|
||||
indexRandom(true, requests);
|
||||
ensureSearchable("test");
|
||||
|
@ -155,7 +184,8 @@ public class ChildrenIT extends ESIntegTestCase {
|
|||
Children childrenBucket = categoryBucket.getAggregations().get("to_comment");
|
||||
assertThat(childrenBucket.getName(), equalTo("to_comment"));
|
||||
assertThat(childrenBucket.getDocCount(), equalTo((long) entry1.getValue().commentIds.size()));
|
||||
assertThat((long) ((InternalAggregation)childrenBucket).getProperty("_count"), equalTo((long) entry1.getValue().commentIds.size()));
|
||||
assertThat((long) ((InternalAggregation)childrenBucket).getProperty("_count"),
|
||||
equalTo((long) entry1.getValue().commentIds.size()));
|
||||
|
||||
Terms commentersTerms = childrenBucket.getAggregations().get("commenters");
|
||||
assertThat((Terms) ((InternalAggregation)childrenBucket).getProperty("commenters"), sameInstance(commentersTerms));
|
||||
|
@ -283,7 +313,7 @@ public class ChildrenIT extends ESIntegTestCase {
|
|||
public void testNonExistingChildType() throws Exception {
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.addAggregation(
|
||||
children("non-existing", "xyz")
|
||||
children("non-existing", "xyz")
|
||||
).get();
|
||||
assertSearchResponse(searchResponse);
|
||||
|
||||
|
@ -304,7 +334,8 @@ children("non-existing", "xyz")
|
|||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex(indexName, masterType, "1").setSource("brand", "Levis", "name", "Style 501", "material", "Denim"));
|
||||
requests.add(client().prepareIndex(indexName, masterType, "1")
|
||||
.setSource("brand", "Levis", "name", "Style 501", "material", "Denim"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "0").setParent("1").setSource("color", "blue", "size", "32"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "1").setParent("1").setSource("color", "blue", "size", "34"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "2").setParent("1").setSource("color", "blue", "size", "36"));
|
||||
|
@ -312,7 +343,8 @@ children("non-existing", "xyz")
|
|||
requests.add(client().prepareIndex(indexName, childType, "4").setParent("1").setSource("color", "black", "size", "40"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "5").setParent("1").setSource("color", "gray", "size", "36"));
|
||||
|
||||
requests.add(client().prepareIndex(indexName, masterType, "2").setSource("brand", "Wrangler", "name", "Regular Cut", "material", "Leather"));
|
||||
requests.add(client().prepareIndex(indexName, masterType, "2")
|
||||
.setSource("brand", "Wrangler", "name", "Regular Cut", "material", "Leather"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "6").setParent("2").setSource("color", "blue", "size", "32"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "7").setParent("2").setSource("color", "blue", "size", "34"));
|
||||
requests.add(client().prepareIndex(indexName, childType, "8").setParent("2").setSource("color", "black", "size", "36"));
|
||||
|
@ -425,7 +457,7 @@ children("non-existing", "xyz")
|
|||
.setSize(0)
|
||||
.addAggregation(AggregationBuilders.terms("towns").field("town")
|
||||
.subAggregation(AggregationBuilders.terms("parent_names").field("name")
|
||||
.subAggregation(AggregationBuilders.children("child_docs", "childType"))
|
||||
.subAggregation(children("child_docs", "childType"))
|
||||
)
|
||||
)
|
||||
.get();
|
||||
|
@ -468,5 +500,4 @@ children("non-existing", "xyz")
|
|||
this.category = category;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,13 +17,22 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.search.aggregations.BaseAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.bucket.children.ChildrenAggregationBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class ChildrenTests extends BaseAggregationTestCase<ChildrenAggregationBuilder> {
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> getPlugins() {
|
||||
return Collections.singleton(ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChildrenAggregationBuilder createTestAggregatorBuilder() {
|
||||
String name = randomAlphaOfLengthBetween(3, 20);
|
|
@ -17,11 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.InternalSingleBucketAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
|
||||
import java.util.List;
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket.children;
|
||||
package org.elasticsearch.join.aggregations;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.SortedDocValuesField;
|
|
@ -16,17 +16,20 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.elasticsearch.search.child;
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
|
||||
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.explain.ExplainResponse;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.lucene.search.function.CombineFunction;
|
||||
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -34,8 +37,6 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
|
@ -43,6 +44,8 @@ import org.elasticsearch.index.query.MatchQueryBuilder;
|
|||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
|
@ -62,6 +65,8 @@ import org.hamcrest.Matchers;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -72,8 +77,6 @@ import java.util.Set;
|
|||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.idsQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
|
@ -83,6 +86,8 @@ import static org.elasticsearch.index.query.QueryBuilders.prefixQuery;
|
|||
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.fieldValueFactorFunction;
|
||||
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.weightFactorFunction;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
|
@ -100,6 +105,21 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
|
||||
@ClusterScope(scope = Scope.SUITE)
|
||||
public class ChildQuerySearchIT extends ESIntegTestCase {
|
||||
|
||||
@Override
|
||||
protected boolean ignoreExternalCluster() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return Collections.singleton(ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
|
||||
return nodePlugins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings indexSettings() {
|
||||
|
@ -145,26 +165,30 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("p1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(hasParentQuery("parent", termQuery("p_field", "p_value1"), false))).execute()
|
||||
.setQuery(boolQuery().must(matchAllQuery())
|
||||
.filter(hasParentQuery("parent", termQuery("p_field", "p_value1"), false))).execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("c1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(hasParentQuery("child", termQuery("c_field", "c_value1"), false))).execute()
|
||||
.setQuery(boolQuery().must(matchAllQuery())
|
||||
.filter(hasParentQuery("child", termQuery("c_field", "c_value1"), false))).execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("gc1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent", termQuery("p_field", "p_value1"), false)).execute()
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", termQuery("p_field", "p_value1"), false)).execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("c1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("child", termQuery("c_field", "c_value1"), false)).execute()
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(hasParentQuery("child", termQuery("c_field", "c_value1"), false)).execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
|
@ -209,7 +233,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
refresh();
|
||||
|
||||
// TEST FETCHING _parent from child
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setQuery(idsQuery("child").addIds("c1")).storedFields("_parent").execute()
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(idsQuery("child").addIds("c1")).storedFields("_parent").execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
|
@ -284,7 +309,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
builders.add(client().prepareIndex("test", "child", Integer.toString(i)).setSource("c_field", i).setParent("" + 0));
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
builders.add(client().prepareIndex("test", "child", Integer.toString(i + 10)).setSource("c_field", i + 10).setParent(Integer.toString(i)));
|
||||
builders.add(client().prepareIndex("test", "child", Integer.toString(i + 10))
|
||||
.setSource("c_field", i + 10).setParent(Integer.toString(i)));
|
||||
}
|
||||
|
||||
if (randomBoolean()) {
|
||||
|
@ -445,9 +471,11 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
|
||||
SearchResponse searchResponse = client()
|
||||
.prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow")), ScoreMode.None))
|
||||
.setQuery(hasChildQuery("child",
|
||||
boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow")), ScoreMode.None))
|
||||
.addAggregation(AggregationBuilders.global("global").subAggregation(
|
||||
AggregationBuilders.filter("filter", boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow"))).subAggregation(
|
||||
AggregationBuilders.filter("filter",
|
||||
boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow"))).subAggregation(
|
||||
AggregationBuilders.terms("facet1").field("c_field")))).get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
|
||||
|
@ -523,7 +551,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
assertNoFailures(searchResponse);
|
||||
|
||||
searchResponse = client().prepareSearch("test").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
|
||||
.setQuery(boolQuery().mustNot(hasParentQuery("parent", boolQuery().should(queryStringQuery("p_field:*")), false))).execute()
|
||||
.setQuery(boolQuery().mustNot(hasParentQuery("parent",
|
||||
boolQuery().should(queryStringQuery("p_field:*")), false))).execute()
|
||||
.actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
}
|
||||
|
@ -570,7 +599,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
.get();
|
||||
assertHitCount(countResponse, 1L);
|
||||
|
||||
countResponse = client().prepareSearch("test").setSize(0).setQuery(hasParentQuery("parent", termQuery("p_field", "1"), true))
|
||||
countResponse = client().prepareSearch("test").setSize(0)
|
||||
.setQuery(hasParentQuery("parent", termQuery("p_field", "1"), true))
|
||||
.get();
|
||||
assertHitCount(countResponse, 1L);
|
||||
|
||||
|
@ -579,7 +609,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
.get();
|
||||
assertHitCount(countResponse, 1L);
|
||||
|
||||
countResponse = client().prepareSearch("test").setSize(0).setQuery(constantScoreQuery(hasParentQuery("parent", termQuery("p_field", "1"), false)))
|
||||
countResponse = client().prepareSearch("test").setSize(0)
|
||||
.setQuery(constantScoreQuery(hasParentQuery("parent", termQuery("p_field", "1"), false)))
|
||||
.get();
|
||||
assertHitCount(countResponse, 1L);
|
||||
}
|
||||
|
@ -685,11 +716,11 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
SearchResponse response = client()
|
||||
.prepareSearch("test")
|
||||
.setQuery(
|
||||
QueryBuilders.hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Total)).get();
|
||||
hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Total)).get();
|
||||
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(3L));
|
||||
assertThat(response.getHits().getHits()[0].getId(), equalTo("1"));
|
||||
|
@ -702,11 +733,11 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
response = client()
|
||||
.prepareSearch("test")
|
||||
.setQuery(
|
||||
QueryBuilders.hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Max)).get();
|
||||
hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Max)).get();
|
||||
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(3L));
|
||||
assertThat(response.getHits().getHits()[0].getId(), equalTo("3"));
|
||||
|
@ -719,11 +750,11 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
response = client()
|
||||
.prepareSearch("test")
|
||||
.setQuery(
|
||||
QueryBuilders.hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Avg)).get();
|
||||
hasChildQuery(
|
||||
"child",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("c_field2", 0),
|
||||
fieldValueFactorFunction("c_field1"))
|
||||
.boostMode(CombineFunction.REPLACE), ScoreMode.Avg)).get();
|
||||
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(3L));
|
||||
assertThat(response.getHits().getHits()[0].getId(), equalTo("3"));
|
||||
|
@ -736,11 +767,11 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
response = client()
|
||||
.prepareSearch("test")
|
||||
.setQuery(
|
||||
QueryBuilders.hasParentQuery(
|
||||
"parent",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("p_field1", "p_value3"),
|
||||
fieldValueFactorFunction("p_field2"))
|
||||
.boostMode(CombineFunction.REPLACE), true))
|
||||
hasParentQuery(
|
||||
"parent",
|
||||
QueryBuilders.functionScoreQuery(matchQuery("p_field1", "p_value3"),
|
||||
fieldValueFactorFunction("p_field2"))
|
||||
.boostMode(CombineFunction.REPLACE), true))
|
||||
.addSort(SortBuilders.fieldSort("c_field3")).addSort(SortBuilders.scoreSort()).get();
|
||||
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(7L));
|
||||
|
@ -769,7 +800,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
ensureGreen();
|
||||
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value"), ScoreMode.None)).get();
|
||||
.setQuery(hasChildQuery("child", matchQuery("text", "value"), ScoreMode.None)).get();
|
||||
assertNoFailures(response);
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(0L));
|
||||
|
||||
|
@ -777,20 +808,21 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
.setRefreshPolicy(RefreshPolicy.IMMEDIATE).get();
|
||||
|
||||
response = client().prepareSearch("test")
|
||||
.setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value"), ScoreMode.None)).get();
|
||||
.setQuery(hasChildQuery("child", matchQuery("text", "value"), ScoreMode.None)).get();
|
||||
assertNoFailures(response);
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(0L));
|
||||
|
||||
response = client().prepareSearch("test").setQuery(QueryBuilders.hasChildQuery("child", matchQuery("text", "value"), ScoreMode.Max))
|
||||
response = client().prepareSearch("test").setQuery(hasChildQuery("child", matchQuery("text", "value"), ScoreMode.Max))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(0L));
|
||||
|
||||
response = client().prepareSearch("test").setQuery(QueryBuilders.hasParentQuery("parent", matchQuery("text", "value"), false)).get();
|
||||
response = client().prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", matchQuery("text", "value"), false)).get();
|
||||
assertNoFailures(response);
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(0L));
|
||||
|
||||
response = client().prepareSearch("test").setQuery(QueryBuilders.hasParentQuery("parent", matchQuery("text", "value"), true))
|
||||
response = client().prepareSearch("test").setQuery(hasParentQuery("parent", matchQuery("text", "value"), true))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertThat(response.getHits().getTotalHits(), equalTo(0L));
|
||||
|
@ -818,7 +850,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(hasParentQuery("parent", termQuery("p_field", 1), false))).get();
|
||||
.setQuery(boolQuery().must(matchAllQuery())
|
||||
.filter(hasParentQuery("parent", termQuery("p_field", 1), false))).get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("2"));
|
||||
|
@ -873,12 +906,14 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
assertSearchHit(searchResponse, 1, hasId("2"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(boolQuery().must(hasChildQuery("child", matchQuery("c_field", 1), ScoreMode.None))))
|
||||
.setQuery(boolQuery().must(matchAllQuery())
|
||||
.filter(boolQuery().must(hasChildQuery("child", matchQuery("c_field", 1), ScoreMode.None))))
|
||||
.get();
|
||||
assertSearchHit(searchResponse, 1, hasId("1"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(boolQuery().must(hasParentQuery("parent", matchQuery("p_field", 1), false)))).get();
|
||||
.setQuery(boolQuery().must(matchAllQuery())
|
||||
.filter(boolQuery().must(hasParentQuery("parent", matchQuery("p_field", 1), false)))).get();
|
||||
assertSearchHit(searchResponse, 1, hasId("2"));
|
||||
}
|
||||
|
||||
|
@ -974,7 +1009,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
client().admin().indices().prepareRefresh("test").get();
|
||||
}
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "yellow"), ScoreMode.Total))
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(hasChildQuery("child", termQuery("c_field", "yellow"), ScoreMode.Total))
|
||||
.get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
|
@ -1009,7 +1045,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
client().prepareIndex("test", "child", "c5").setSource("c_field", "x").setParent("p2").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", matchAllQuery(), ScoreMode.Total))
|
||||
SearchResponse searchResponse = client()
|
||||
.prepareSearch("test").setQuery(hasChildQuery("child", matchAllQuery(), ScoreMode.Total))
|
||||
.setMinScore(3) // Score needs to be 3 or above!
|
||||
.get();
|
||||
assertNoFailures(searchResponse);
|
||||
|
@ -1219,7 +1256,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
createIndex("test");
|
||||
ensureGreen();
|
||||
|
||||
PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("child").setSource("number", "type=integer")
|
||||
PutMappingResponse putMappingResponse = client().admin().indices()
|
||||
.preparePutMapping("test").setType("child").setSource("number", "type=integer")
|
||||
.get();
|
||||
assertThat(putMappingResponse.isAcknowledged(), equalTo(true));
|
||||
|
||||
|
@ -1269,13 +1307,15 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
|
||||
ScoreMode scoreMode = randomFrom(ScoreMode.values());
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(QueryBuilders.hasChildQuery("child", termQuery("c_field", "blue"), scoreMode)).filter(boolQuery().mustNot(termQuery("p_field", "3"))))
|
||||
.setQuery(boolQuery().must(hasChildQuery("child", termQuery("c_field", "blue"), scoreMode))
|
||||
.filter(boolQuery().mustNot(termQuery("p_field", "3"))))
|
||||
.get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(QueryBuilders.hasChildQuery("child", termQuery("c_field", "red"), scoreMode)).filter(boolQuery().mustNot(termQuery("p_field", "3"))))
|
||||
.setQuery(boolQuery().must(hasChildQuery("child", termQuery("c_field", "red"), scoreMode))
|
||||
.filter(boolQuery().mustNot(termQuery("p_field", "3"))))
|
||||
.get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
|
||||
|
@ -1293,25 +1333,29 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get();
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "1"), ScoreMode.Max).queryName("test"))
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child",
|
||||
termQuery("c_field", "1"), ScoreMode.Max).queryName("test"))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1L);
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent", termQuery("p_field", "1"), true).queryName("test"))
|
||||
searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent",
|
||||
termQuery("p_field", "1"), true).queryName("test"))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1L);
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildQuery("child", termQuery("c_field", "1"), ScoreMode.None).queryName("test")))
|
||||
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildQuery("child",
|
||||
termQuery("c_field", "1"), ScoreMode.None).queryName("test")))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1L);
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test"));
|
||||
|
||||
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasParentQuery("parent", termQuery("p_field", "1"), false).queryName("test")))
|
||||
searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasParentQuery("parent",
|
||||
termQuery("p_field", "1"), false).queryName("test")))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1L);
|
||||
assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
|
@ -1400,7 +1444,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
for (int i = 0; i < 2; i++) {
|
||||
SearchResponse searchResponse = client().prepareSearch()
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(boolQuery()
|
||||
.must(QueryBuilders.hasChildQuery("child", matchQuery("c_field", "red"), ScoreMode.None))
|
||||
.must(hasChildQuery("child", matchQuery("c_field", "red"), ScoreMode.None))
|
||||
.must(matchAllQuery())))
|
||||
.get();
|
||||
assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
|
||||
|
@ -1412,7 +1456,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
|
||||
SearchResponse searchResponse = client().prepareSearch()
|
||||
.setQuery(boolQuery().must(matchAllQuery()).filter(boolQuery()
|
||||
.must(QueryBuilders.hasChildQuery("child", matchQuery("c_field", "red"), ScoreMode.None))
|
||||
.must(hasChildQuery("child", matchQuery("c_field", "red"), ScoreMode.None))
|
||||
.must(matchAllQuery())))
|
||||
.get();
|
||||
|
||||
|
@ -1478,7 +1522,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
|
||||
SearchResponse resp;
|
||||
resp = client().prepareSearch("test")
|
||||
.setSource(new SearchSourceBuilder().query(QueryBuilders.hasChildQuery("posts", QueryBuilders.matchQuery("field", "bar"), ScoreMode.None)))
|
||||
.setSource(new SearchSourceBuilder().query(hasChildQuery("posts",
|
||||
QueryBuilders.matchQuery("field", "bar"), ScoreMode.None)))
|
||||
.get();
|
||||
assertHitCount(resp, 1L);
|
||||
}
|
||||
|
@ -1580,8 +1625,10 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
QueryBuilders.functionScoreQuery(constantScoreQuery(QueryBuilders.termQuery("foo", "two")),
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(weightFactorFunction(1)),
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("foo", "three"), weightFactorFunction(1)),
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("foo", "four"), weightFactorFunction(1))
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("foo", "three"),
|
||||
weightFactorFunction(1)),
|
||||
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("foo", "four"),
|
||||
weightFactorFunction(1))
|
||||
}).boostMode(CombineFunction.REPLACE).scoreMode(FiltersFunctionScoreQuery.ScoreMode.SUM), scoreMode)
|
||||
.minMaxChildren(minChildren, maxChildren != null ? maxChildren : HasChildQueryBuilder.DEFAULT_MAX_CHILDREN);
|
||||
|
||||
|
@ -1916,7 +1963,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
|
||||
try {
|
||||
client().prepareSearch("test")
|
||||
.setQuery(QueryBuilders.hasChildQuery("child", matchAllQuery(), ScoreMode.None))
|
||||
.setQuery(hasChildQuery("child", matchAllQuery(), ScoreMode.None))
|
||||
.get();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
|
@ -1932,7 +1979,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
refresh();
|
||||
//make sure that when we explicitly set a type, the inner query is executed in the context of the parent type instead
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setTypes("child-type").setQuery(
|
||||
QueryBuilders.hasParentQuery("parent-type", new IdsQueryBuilder().addIds("parent-id"), false)).get();
|
||||
hasParentQuery("parent-type", new IdsQueryBuilder().addIds("parent-id"), false)).get();
|
||||
assertSearchHits(searchResponse, "child-id");
|
||||
}
|
||||
|
||||
|
@ -1945,7 +1992,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
refresh();
|
||||
//make sure that when we explicitly set a type, the inner query is executed in the context of the child type instead
|
||||
SearchResponse searchResponse = client().prepareSearch("test").setTypes("parent-type").setQuery(
|
||||
QueryBuilders.hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"), ScoreMode.None)).get();
|
||||
hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"), ScoreMode.None)).get();
|
||||
assertSearchHits(searchResponse, "parent-id");
|
||||
}
|
||||
|
||||
|
@ -1955,8 +2002,10 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
.addMapping("parent-type", "searchText", "type=text,term_vector=with_positions_offsets,index_options=offsets")
|
||||
.addMapping("child-type", "_parent", "type=parent-type", "searchText",
|
||||
"type=text,term_vector=with_positions_offsets,index_options=offsets"));
|
||||
client().prepareIndex("test", "parent-type", "parent-id").setSource("searchText", "quick brown fox").get();
|
||||
client().prepareIndex("test", "child-type", "child-id").setParent("parent-id").setSource("searchText", "quick brown fox").get();
|
||||
client().prepareIndex("test", "parent-type", "parent-id")
|
||||
.setSource("searchText", "quick brown fox").get();
|
||||
client().prepareIndex("test", "child-type", "child-id")
|
||||
.setParent("parent-id").setSource("searchText", "quick brown fox").get();
|
||||
refresh();
|
||||
|
||||
String[] highlightTypes = new String[] {"plain", "fvh", "postings"};
|
||||
|
@ -1988,4 +2037,177 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testAliasesFilterWithHasChildQuery() throws Exception {
|
||||
assertAcked(prepareCreate("my-index")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent")
|
||||
.addMapping("child", "_parent", "type=parent")
|
||||
);
|
||||
client().prepareIndex("my-index", "parent", "1").setSource("{}", XContentType.JSON).get();
|
||||
client().prepareIndex("my-index", "child", "2").setSource("{}", XContentType.JSON).setParent("1").get();
|
||||
refresh();
|
||||
|
||||
assertAcked(admin().indices().prepareAliases().addAlias("my-index", "filter1",
|
||||
hasChildQuery("child", matchAllQuery(), ScoreMode.None)));
|
||||
assertAcked(admin().indices().prepareAliases().addAlias("my-index", "filter2",
|
||||
hasParentQuery("parent", matchAllQuery(), false)));
|
||||
|
||||
SearchResponse response = client().prepareSearch("filter1").get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
response = client().prepareSearch("filter2").get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("2"));
|
||||
}
|
||||
|
||||
/*
|
||||
Test for https://github.com/elastic/elasticsearch/issues/3444
|
||||
*/
|
||||
public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
|
||||
client().admin().indices().prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
|
||||
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON)
|
||||
.execute().actionGet();
|
||||
ensureGreen();
|
||||
|
||||
BulkRequestBuilder builder = client().prepareBulk();
|
||||
|
||||
// It's important to use JSON parsing here and request objects: issue 3444 is related to incomplete option parsing
|
||||
byte[] addParent = new BytesArray(
|
||||
"{" +
|
||||
" \"index\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"parent\"," +
|
||||
" \"_id\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"doc\" : {" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
" }," +
|
||||
" \"doc_as_upsert\" : \"true\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
builder.add(addParent, 0, addParent.length, XContentType.JSON);
|
||||
builder.add(addChild, 0, addChild.length, XContentType.JSON);
|
||||
|
||||
BulkResponse bulkResponse = builder.get();
|
||||
assertThat(bulkResponse.getItems().length, equalTo(2));
|
||||
assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
|
||||
|
||||
client().admin().indices().prepareRefresh("test").get();
|
||||
|
||||
//we check that the _parent field was set on the child document by using the has parent query
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(searchResponse);
|
||||
assertSearchHits(searchResponse, "child1");
|
||||
}
|
||||
|
||||
/*
|
||||
Test for https://github.com/elastic/elasticsearch/issues/3444
|
||||
*/
|
||||
public void testBulkUpdateUpsertWithParent() throws Exception {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
|
||||
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
|
||||
ensureGreen();
|
||||
|
||||
BulkRequestBuilder builder = client().prepareBulk();
|
||||
|
||||
byte[] addParent = new BytesArray(
|
||||
"{" +
|
||||
" \"index\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"parent\"," +
|
||||
" \"_id\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"field1\" : \"value1\"" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild1 = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"script\" : {" +
|
||||
" \"inline\" : \"ctx._source.field2 = 'value2'\"" +
|
||||
" }," +
|
||||
" \"lang\" : \"" + InnerHitsIT.CustomScriptPlugin.NAME + "\"," +
|
||||
" \"upsert\" : {" +
|
||||
" \"field1\" : \"value1'\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
byte[] addChild2 = new BytesArray(
|
||||
"{" +
|
||||
" \"update\" : {" +
|
||||
" \"_index\" : \"test\"," +
|
||||
" \"_type\" : \"child\"," +
|
||||
" \"_id\" : \"child1\"," +
|
||||
" \"parent\" : \"parent1\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n" +
|
||||
"{" +
|
||||
" \"script\" : \"ctx._source.field2 = 'value2'\"," +
|
||||
" \"upsert\" : {" +
|
||||
" \"field1\" : \"value1'\"" +
|
||||
" }" +
|
||||
"}" +
|
||||
"\n").array();
|
||||
|
||||
builder.add(addParent, 0, addParent.length, XContentType.JSON);
|
||||
builder.add(addChild1, 0, addChild1.length, XContentType.JSON);
|
||||
builder.add(addChild2, 0, addChild2.length, XContentType.JSON);
|
||||
|
||||
BulkResponse bulkResponse = builder.get();
|
||||
assertThat(bulkResponse.getItems().length, equalTo(3));
|
||||
assertThat(bulkResponse.getItems()[0].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[1].isFailed(), equalTo(false));
|
||||
assertThat(bulkResponse.getItems()[2].isFailed(), equalTo(true));
|
||||
assertThat(bulkResponse.getItems()[2].getFailure().getCause().getCause().getMessage(),
|
||||
equalTo("script_lang not supported [painless]"));
|
||||
|
||||
client().admin().indices().prepareRefresh("test").get();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(hasParentQuery("parent", QueryBuilders.matchAllQuery(), false))
|
||||
.get();
|
||||
|
||||
assertSearchHits(searchResponse, "child1");
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.query;
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||
import org.apache.lucene.search.TermInSetQuery;
|
||||
|
@ -40,7 +40,17 @@ import org.elasticsearch.index.mapper.MapperService;
|
|||
import org.elasticsearch.index.mapper.TypeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.Uid;
|
||||
import org.elasticsearch.index.mapper.UidFieldMapper;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
import org.elasticsearch.index.query.WrapperQueryBuilder;
|
||||
import org.elasticsearch.index.similarity.SimilarityService;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.search.fetch.subphase.InnerHitsContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||
|
@ -48,10 +58,12 @@ import org.elasticsearch.search.sort.SortOrder;
|
|||
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
|
@ -65,6 +77,11 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
|
||||
boolean requiresRewrite = false;
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> getPlugins() {
|
||||
return Collections.singletonList(ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
|
||||
similarity = randomFrom("classic", "BM25");
|
||||
|
@ -97,7 +114,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
int min = randomIntBetween(0, Integer.MAX_VALUE / 2);
|
||||
int max = randomIntBetween(min, Integer.MAX_VALUE);
|
||||
|
||||
QueryBuilder innerQueryBuilder = RandomQueryBuilder.createQuery(random());
|
||||
QueryBuilder innerQueryBuilder = new MatchAllQueryBuilder();
|
||||
if (randomBoolean()) {
|
||||
requiresRewrite = true;
|
||||
innerQueryBuilder = new WrapperQueryBuilder(innerQueryBuilder.toString());
|
||||
|
@ -144,19 +161,19 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
}
|
||||
|
||||
public void testIllegalValues() {
|
||||
QueryBuilder query = RandomQueryBuilder.createQuery(random());
|
||||
QueryBuilder query = new MatchAllQueryBuilder();
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> QueryBuilders.hasChildQuery(null, query, ScoreMode.None));
|
||||
() -> hasChildQuery(null, query, ScoreMode.None));
|
||||
assertEquals("[has_child] requires 'type' field", e.getMessage());
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> QueryBuilders.hasChildQuery("foo", null, ScoreMode.None));
|
||||
e = expectThrows(IllegalArgumentException.class, () -> hasChildQuery("foo", null, ScoreMode.None));
|
||||
assertEquals("[has_child] requires 'query' field", e.getMessage());
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> QueryBuilders.hasChildQuery("foo", query, null));
|
||||
e = expectThrows(IllegalArgumentException.class, () -> hasChildQuery("foo", query, null));
|
||||
assertEquals("[has_child] requires 'score_mode' field", e.getMessage());
|
||||
|
||||
int positiveValue = randomIntBetween(0, Integer.MAX_VALUE);
|
||||
HasChildQueryBuilder foo = QueryBuilders.hasChildQuery("foo", query, ScoreMode.None); // all good
|
||||
HasChildQueryBuilder foo = hasChildQuery("foo", query, ScoreMode.None); // all good
|
||||
e = expectThrows(IllegalArgumentException.class, () -> foo.minMaxChildren(randomIntBetween(Integer.MIN_VALUE, -1), positiveValue));
|
||||
assertEquals("[has_child] requires non-negative 'min_children' field", e.getMessage());
|
||||
|
||||
|
@ -225,7 +242,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
String[] searchTypes = new String[]{PARENT_TYPE};
|
||||
QueryShardContext shardContext = createShardContext();
|
||||
shardContext.setTypes(searchTypes);
|
||||
HasChildQueryBuilder hasChildQueryBuilder = QueryBuilders.hasChildQuery(CHILD_TYPE, new IdsQueryBuilder().addIds("id"), ScoreMode.None);
|
||||
HasChildQueryBuilder hasChildQueryBuilder = hasChildQuery(CHILD_TYPE, new IdsQueryBuilder().addIds("id"), ScoreMode.None);
|
||||
Query query = hasChildQueryBuilder.toQuery(shardContext);
|
||||
//verify that the context types are still the same as the ones we previously set
|
||||
assertThat(shardContext.getTypes(), equalTo(searchTypes));
|
||||
|
@ -252,7 +269,8 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
assertThat(booleanTermsQuery.clauses().get(0).getQuery(), instanceOf(TermQuery.class));
|
||||
TermQuery termQuery = (TermQuery) booleanTermsQuery.clauses().get(0).getQuery();
|
||||
assertThat(termQuery.getTerm().field(), equalTo(UidFieldMapper.NAME));
|
||||
//we want to make sure that the inner ids query gets executed against the child type rather than the main type we initially set to the context
|
||||
//we want to make sure that the inner ids query gets executed against the child type rather
|
||||
// than the main type we initially set to the context
|
||||
BytesRef[] ids = Uid.createUidsForTypesAndIds(Collections.singletonList(type), Collections.singletonList(id));
|
||||
assertThat(termQuery.getTerm().bytes(), equalTo(ids[0]));
|
||||
//check the type filter
|
||||
|
@ -273,7 +291,8 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
|
||||
public void testNonDefaultSimilarity() throws Exception {
|
||||
QueryShardContext shardContext = createShardContext();
|
||||
HasChildQueryBuilder hasChildQueryBuilder = QueryBuilders.hasChildQuery(CHILD_TYPE, new TermQueryBuilder("custom_string", "value"), ScoreMode.None);
|
||||
HasChildQueryBuilder hasChildQueryBuilder =
|
||||
hasChildQuery(CHILD_TYPE, new TermQueryBuilder("custom_string", "value"), ScoreMode.None);
|
||||
HasChildQueryBuilder.LateParsingQuery query = (HasChildQueryBuilder.LateParsingQuery) hasChildQueryBuilder.toQuery(shardContext);
|
||||
Similarity expected = SimilarityService.BUILT_IN.get(similarity)
|
||||
.apply(similarity, Settings.EMPTY, Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build())
|
||||
|
@ -281,48 +300,6 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
assertThat(((PerFieldSimilarityWrapper) query.getSimilarity()).get("custom_string"), instanceOf(expected.getClass()));
|
||||
}
|
||||
|
||||
public void testMinFromString() {
|
||||
assertThat("fromString(min) != MIN", ScoreMode.Min, equalTo(HasChildQueryBuilder.parseScoreMode("min")));
|
||||
assertThat("min", equalTo(HasChildQueryBuilder.scoreModeAsString(ScoreMode.Min)));
|
||||
}
|
||||
|
||||
public void testMaxFromString() {
|
||||
assertThat("fromString(max) != MAX", ScoreMode.Max, equalTo(HasChildQueryBuilder.parseScoreMode("max")));
|
||||
assertThat("max", equalTo(HasChildQueryBuilder.scoreModeAsString(ScoreMode.Max)));
|
||||
}
|
||||
|
||||
public void testAvgFromString() {
|
||||
assertThat("fromString(avg) != AVG", ScoreMode.Avg, equalTo(HasChildQueryBuilder.parseScoreMode("avg")));
|
||||
assertThat("avg", equalTo(HasChildQueryBuilder.scoreModeAsString(ScoreMode.Avg)));
|
||||
}
|
||||
|
||||
public void testSumFromString() {
|
||||
assertThat("fromString(total) != SUM", ScoreMode.Total, equalTo(HasChildQueryBuilder.parseScoreMode("sum")));
|
||||
assertThat("sum", equalTo(HasChildQueryBuilder.scoreModeAsString(ScoreMode.Total)));
|
||||
}
|
||||
|
||||
public void testNoneFromString() {
|
||||
assertThat("fromString(none) != NONE", ScoreMode.None, equalTo(HasChildQueryBuilder.parseScoreMode("none")));
|
||||
assertThat("none", equalTo(HasChildQueryBuilder.scoreModeAsString(ScoreMode.None)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should throw {@link IllegalArgumentException} instead of NPE.
|
||||
*/
|
||||
public void testThatNullFromStringThrowsException() {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> HasChildQueryBuilder.parseScoreMode(null));
|
||||
assertEquals("No score mode for child query [null] found", e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Failure should not change (and the value should never match anything...).
|
||||
*/
|
||||
public void testThatUnrecognizedFromStringThrowsException() {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> HasChildQueryBuilder.parseScoreMode("unrecognized value"));
|
||||
assertEquals("No score mode for child query [unrecognized value] found", e.getMessage());
|
||||
}
|
||||
|
||||
public void testIgnoreUnmapped() throws IOException {
|
||||
final HasChildQueryBuilder queryBuilder = new HasChildQueryBuilder("unmapped", new MatchAllQueryBuilder(), ScoreMode.None);
|
||||
queryBuilder.ignoreUnmapped(true);
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.query;
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
@ -28,6 +28,16 @@ import org.elasticsearch.common.xcontent.ToXContent;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
import org.elasticsearch.index.query.WrapperQueryBuilder;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.search.fetch.subphase.InnerHitsContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||
|
@ -35,9 +45,12 @@ import org.elasticsearch.search.sort.SortOrder;
|
|||
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
|
@ -49,6 +62,11 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
|
||||
boolean requiresRewrite = false;
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> getPlugins() {
|
||||
return Collections.singletonList(ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
|
||||
mapperService.merge(PARENT_TYPE, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(PARENT_TYPE,
|
||||
|
@ -79,7 +97,7 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
*/
|
||||
@Override
|
||||
protected HasParentQueryBuilder doCreateTestQueryBuilder() {
|
||||
QueryBuilder innerQueryBuilder = RandomQueryBuilder.createQuery(random());
|
||||
QueryBuilder innerQueryBuilder = new MatchAllQueryBuilder();
|
||||
if (randomBoolean()) {
|
||||
requiresRewrite = true;
|
||||
innerQueryBuilder = new WrapperQueryBuilder(innerQueryBuilder.toString());
|
||||
|
@ -124,17 +142,17 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
}
|
||||
|
||||
public void testIllegalValues() throws IOException {
|
||||
QueryBuilder query = RandomQueryBuilder.createQuery(random());
|
||||
QueryBuilder query = new MatchAllQueryBuilder();
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> QueryBuilders.hasParentQuery(null, query, false));
|
||||
() -> hasParentQuery(null, query, false));
|
||||
assertThat(e.getMessage(), equalTo("[has_parent] requires 'type' field"));
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class,
|
||||
() -> QueryBuilders.hasParentQuery("foo", null, false));
|
||||
() -> hasParentQuery("foo", null, false));
|
||||
assertThat(e.getMessage(), equalTo("[has_parent] requires 'query' field"));
|
||||
|
||||
QueryShardContext context = createShardContext();
|
||||
HasParentQueryBuilder qb = QueryBuilders.hasParentQuery("just_a_type", new MatchAllQueryBuilder(), false);
|
||||
HasParentQueryBuilder qb = hasParentQuery("just_a_type", new MatchAllQueryBuilder(), false);
|
||||
QueryShardException qse = expectThrows(QueryShardException.class, () -> qb.doToQuery(context));
|
||||
assertThat(qse.getMessage(), equalTo("[has_parent] no child types found for type [just_a_type]"));
|
||||
}
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.join.query;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.MockScriptEngine;
|
||||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHits;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilders;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.ESIntegTestCase.Scope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHit;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
@ClusterScope(scope = Scope.SUITE)
|
||||
public class InnerHitsIT extends ESIntegTestCase {
|
||||
@Override
|
||||
protected boolean ignoreExternalCluster() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return Arrays.asList(ParentJoinPlugin.class, CustomScriptPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
|
||||
return nodePlugins();
|
||||
}
|
||||
|
||||
public static class CustomScriptPlugin extends MockScriptPlugin {
|
||||
@Override
|
||||
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
|
||||
return Collections.singletonMap("5", script -> "5");
|
||||
}
|
||||
}
|
||||
|
||||
public void testSimpleParentChild() throws Exception {
|
||||
assertAcked(prepareCreate("articles")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("article", "title", "type=text")
|
||||
.addMapping("comment", "_parent", "type=article", "message", "type=text,fielddata=true")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("articles", "article", "1").setSource("title", "quick brown fox"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "1").setParent("1").setSource("message", "fox eat quick"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "2").setParent("1").setSource("message", "fox ate rabbit x y z"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "3").setParent("1").setSource("message", "rabbit got away"));
|
||||
requests.add(client().prepareIndex("articles", "article", "2").setSource("title", "big gray elephant"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "4").setParent("2").setSource("message", "elephant captured"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "5").setParent("2").setSource("message", "mice squashed by elephant x"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "6").setParent("2").setSource("message", "elephant scared by mice x y"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("1"));
|
||||
assertThat(response.getHits().getAt(0).getShard(), notNullValue());
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(2L));
|
||||
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(1).getType(), equalTo("comment"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment", matchQuery("message", "elephant"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("2"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(3L));
|
||||
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("4"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("5"));
|
||||
assertThat(innerHits.getAt(1).getType(), equalTo("comment"));
|
||||
assertThat(innerHits.getAt(2).getId(), equalTo("6"));
|
||||
assertThat(innerHits.getAt(2).getType(), equalTo("comment"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(
|
||||
hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None).innerHit(
|
||||
new InnerHitBuilder()
|
||||
.addDocValueField("message")
|
||||
.setHighlightBuilder(new HighlightBuilder().field("message"))
|
||||
.setExplain(true).setSize(1)
|
||||
.addScriptField("script", new Script(ScriptType.INLINE, MockScriptEngine.NAME, "5",
|
||||
Collections.emptyMap())),
|
||||
false)
|
||||
).get();
|
||||
assertNoFailures(response);
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getHits().length, equalTo(1));
|
||||
assertThat(innerHits.getAt(0).getHighlightFields().get("message").getFragments()[0].string(), equalTo("<em>fox</em> eat quick"));
|
||||
assertThat(innerHits.getAt(0).getExplanation().toString(), containsString("weight(message:fox"));
|
||||
assertThat(innerHits.getAt(0).getFields().get("message").getValue().toString(), equalTo("eat"));
|
||||
assertThat(innerHits.getAt(0).getFields().get("script").getValue().toString(), equalTo("5"));
|
||||
}
|
||||
|
||||
public void testRandomParentChild() throws Exception {
|
||||
assertAcked(prepareCreate("idx")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent")
|
||||
.addMapping("child1", "_parent", "type=parent")
|
||||
.addMapping("child2", "_parent", "type=parent")
|
||||
);
|
||||
int numDocs = scaledRandomIntBetween(5, 50);
|
||||
List<IndexRequestBuilder> requestBuilders = new ArrayList<>();
|
||||
|
||||
int child1 = 0;
|
||||
int child2 = 0;
|
||||
int[] child1InnerObjects = new int[numDocs];
|
||||
int[] child2InnerObjects = new int[numDocs];
|
||||
for (int parent = 0; parent < numDocs; parent++) {
|
||||
String parentId = String.format(Locale.ENGLISH, "%03d", parent);
|
||||
requestBuilders.add(client().prepareIndex("idx", "parent", parentId).setSource("{}", XContentType.JSON));
|
||||
|
||||
int numChildDocs = child1InnerObjects[parent] = scaledRandomIntBetween(1, numDocs);
|
||||
int limit = child1 + numChildDocs;
|
||||
for (; child1 < limit; child1++) {
|
||||
requestBuilders.add(client().prepareIndex("idx", "child1",
|
||||
String.format(Locale.ENGLISH, "%04d", child1)).setParent(parentId).setSource("{}", XContentType.JSON));
|
||||
}
|
||||
numChildDocs = child2InnerObjects[parent] = scaledRandomIntBetween(1, numDocs);
|
||||
limit = child2 + numChildDocs;
|
||||
for (; child2 < limit; child2++) {
|
||||
requestBuilders.add(client().prepareIndex("idx", "child2",
|
||||
String.format(Locale.ENGLISH, "%04d", child2)).setParent(parentId).setSource("{}", XContentType.JSON));
|
||||
}
|
||||
}
|
||||
indexRandom(true, requestBuilders);
|
||||
|
||||
int size = randomIntBetween(0, numDocs);
|
||||
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
|
||||
boolQuery.should(constantScoreQuery(hasChildQuery("child1", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("a")
|
||||
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
|
||||
boolQuery.should(constantScoreQuery(hasChildQuery("child2", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("b")
|
||||
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
|
||||
SearchResponse searchResponse = client().prepareSearch("idx")
|
||||
.setSize(numDocs)
|
||||
.setTypes("parent")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(boolQuery)
|
||||
.get();
|
||||
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, numDocs);
|
||||
assertThat(searchResponse.getHits().getHits().length, equalTo(numDocs));
|
||||
|
||||
int offset1 = 0;
|
||||
int offset2 = 0;
|
||||
for (int parent = 0; parent < numDocs; parent++) {
|
||||
SearchHit searchHit = searchResponse.getHits().getAt(parent);
|
||||
assertThat(searchHit.getType(), equalTo("parent"));
|
||||
assertThat(searchHit.getId(), equalTo(String.format(Locale.ENGLISH, "%03d", parent)));
|
||||
assertThat(searchHit.getShard(), notNullValue());
|
||||
|
||||
SearchHits inner = searchHit.getInnerHits().get("a");
|
||||
assertThat(inner.getTotalHits(), equalTo((long) child1InnerObjects[parent]));
|
||||
for (int child = 0; child < child1InnerObjects[parent] && child < size; child++) {
|
||||
SearchHit innerHit = inner.getAt(child);
|
||||
assertThat(innerHit.getType(), equalTo("child1"));
|
||||
String childId = String.format(Locale.ENGLISH, "%04d", offset1 + child);
|
||||
assertThat(innerHit.getId(), equalTo(childId));
|
||||
assertThat(innerHit.getNestedIdentity(), nullValue());
|
||||
}
|
||||
offset1 += child1InnerObjects[parent];
|
||||
|
||||
inner = searchHit.getInnerHits().get("b");
|
||||
assertThat(inner.getTotalHits(), equalTo((long) child2InnerObjects[parent]));
|
||||
for (int child = 0; child < child2InnerObjects[parent] && child < size; child++) {
|
||||
SearchHit innerHit = inner.getAt(child);
|
||||
assertThat(innerHit.getType(), equalTo("child2"));
|
||||
String childId = String.format(Locale.ENGLISH, "%04d", offset2 + child);
|
||||
assertThat(innerHit.getId(), equalTo(childId));
|
||||
assertThat(innerHit.getNestedIdentity(), nullValue());
|
||||
}
|
||||
offset2 += child2InnerObjects[parent];
|
||||
}
|
||||
}
|
||||
|
||||
public void testInnerHitsOnHasParent() throws Exception {
|
||||
assertAcked(prepareCreate("stack")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("question", "body", "type=text")
|
||||
.addMapping("answer", "_parent", "type=question", "body", "type=text")
|
||||
);
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("stack", "question", "1").setSource("body", "I'm using HTTPS + Basic authentication "
|
||||
+ "to protect a resource. How can I throttle authentication attempts to protect against brute force attacks?"));
|
||||
requests.add(client().prepareIndex("stack", "answer", "1").setParent("1").setSource("body",
|
||||
"install fail2ban and enable rules for apache"));
|
||||
requests.add(client().prepareIndex("stack", "question", "2").setSource("body",
|
||||
"I have firewall rules set up and also denyhosts installed.\\ndo I also need to install fail2ban?"));
|
||||
requests.add(client().prepareIndex("stack", "answer", "2").setParent("2").setSource("body",
|
||||
"Denyhosts protects only ssh; Fail2Ban protects all daemons."));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("stack")
|
||||
.setTypes("answer")
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.setQuery(
|
||||
boolQuery()
|
||||
.must(matchQuery("body", "fail2ban"))
|
||||
.must(hasParentQuery("question", matchAllQuery(), false).innerHit(new InnerHitBuilder(), false))
|
||||
).get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
|
||||
SearchHit searchHit = response.getHits().getAt(0);
|
||||
assertThat(searchHit.getId(), equalTo("1"));
|
||||
assertThat(searchHit.getType(), equalTo("answer"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getTotalHits(), equalTo(1L));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getType(), equalTo("question"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getId(), equalTo("1"));
|
||||
|
||||
searchHit = response.getHits().getAt(1);
|
||||
assertThat(searchHit.getId(), equalTo("2"));
|
||||
assertThat(searchHit.getType(), equalTo("answer"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getTotalHits(), equalTo(1L));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getType(), equalTo("question"));
|
||||
assertThat(searchHit.getInnerHits().get("question").getAt(0).getId(), equalTo("2"));
|
||||
}
|
||||
|
||||
public void testParentChildMultipleLayers() throws Exception {
|
||||
assertAcked(prepareCreate("articles")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("article", "title", "type=text")
|
||||
.addMapping("comment", "_parent", "type=article", "message", "type=text")
|
||||
.addMapping("remark", "_parent", "type=comment", "message", "type=text")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("articles", "article", "1").setSource("title", "quick brown fox"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "1").setParent("1").setSource("message", "fox eat quick"));
|
||||
requests.add(client().prepareIndex("articles", "remark", "1").setParent("1").setRouting("1").setSource("message", "good"));
|
||||
requests.add(client().prepareIndex("articles", "article", "2").setSource("title", "big gray elephant"));
|
||||
requests.add(client().prepareIndex("articles", "comment", "2").setParent("2").setSource("message", "elephant captured"));
|
||||
requests.add(client().prepareIndex("articles", "remark", "2").setParent("2").setRouting("2").setSource("message", "bad"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment",
|
||||
hasChildQuery("remark", matchQuery("message", "good"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("1"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
|
||||
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("remark"));
|
||||
|
||||
response = client().prepareSearch("articles")
|
||||
.setQuery(hasChildQuery("comment",
|
||||
hasChildQuery("remark", matchQuery("message", "bad"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
|
||||
.get();
|
||||
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
assertSearchHit(response, 1, hasId("2"));
|
||||
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("comment"));
|
||||
|
||||
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
|
||||
assertThat(innerHits.getAt(0).getType(), equalTo("remark"));
|
||||
}
|
||||
|
||||
public void testRoyals() throws Exception {
|
||||
assertAcked(
|
||||
prepareCreate("royals")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("king")
|
||||
.addMapping("prince", "_parent", "type=king")
|
||||
.addMapping("duke", "_parent", "type=prince")
|
||||
.addMapping("earl", "_parent", "type=duke")
|
||||
.addMapping("baron", "_parent", "type=earl")
|
||||
);
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("royals", "king", "king").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "prince", "prince").setParent("king").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "duke", "duke").setParent("prince").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl1").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl2").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl3").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "earl", "earl4").setParent("duke").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron1").setParent("earl1").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron2").setParent("earl2").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron3").setParent("earl3").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("royals", "baron", "baron4").setParent("earl4").setRouting("king")
|
||||
.setSource("{}", XContentType.JSON));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("royals")
|
||||
.setTypes("duke")
|
||||
.setQuery(boolQuery()
|
||||
.filter(hasParentQuery("prince",
|
||||
hasParentQuery("king", matchAllQuery(), false).innerHit(new InnerHitBuilder().setName("kings"), false),
|
||||
false).innerHit(new InnerHitBuilder().setName("princes"), false)
|
||||
)
|
||||
.filter(hasChildQuery("earl",
|
||||
hasChildQuery("baron", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setName("barons"), false),
|
||||
ScoreMode.None).innerHit(new InnerHitBuilder()
|
||||
.addSort(SortBuilders.fieldSort("_uid").order(SortOrder.ASC))
|
||||
.setName("earls")
|
||||
.setSize(4), false)
|
||||
)
|
||||
)
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("duke"));
|
||||
|
||||
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("earls");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(4L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("earl1"));
|
||||
assertThat(innerHits.getAt(1).getId(), equalTo("earl2"));
|
||||
assertThat(innerHits.getAt(2).getId(), equalTo("earl3"));
|
||||
assertThat(innerHits.getAt(3).getId(), equalTo("earl4"));
|
||||
|
||||
SearchHits innerInnerHits = innerHits.getAt(0).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron1"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(1).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron2"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(2).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron3"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(3).getInnerHits().get("barons");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("baron4"));
|
||||
|
||||
innerHits = response.getHits().getAt(0).getInnerHits().get("princes");
|
||||
assertThat(innerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerHits.getAt(0).getId(), equalTo("prince"));
|
||||
|
||||
innerInnerHits = innerHits.getAt(0).getInnerHits().get("kings");
|
||||
assertThat(innerInnerHits.getTotalHits(), equalTo(1L));
|
||||
assertThat(innerInnerHits.getAt(0).getId(), equalTo("king"));
|
||||
}
|
||||
|
||||
public void testMatchesQueriesParentChildInnerHits() throws Exception {
|
||||
assertAcked(prepareCreate("index")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child", "_parent", "type=parent"));
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("index", "parent", "1").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index", "child", "1").setParent("1").setSource("field", "value1"));
|
||||
requests.add(client().prepareIndex("index", "child", "2").setParent("1").setSource("field", "value2"));
|
||||
requests.add(client().prepareIndex("index", "parent", "2").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index", "child", "3").setParent("2").setSource("field", "value1"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("index")
|
||||
.setQuery(hasChildQuery("child", matchQuery("field", "value1").queryName("_name1"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false))
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.get();
|
||||
assertHitCount(response, 2);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name1"));
|
||||
|
||||
assertThat(response.getHits().getAt(1).getId(), equalTo("2"));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name1"));
|
||||
|
||||
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value2").queryName("_name2"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false);
|
||||
response = client().prepareSearch("index")
|
||||
.setQuery(query)
|
||||
.addSort("_uid", SortOrder.ASC)
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getTotalHits(), equalTo(1L));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries().length, equalTo(1));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name2"));
|
||||
}
|
||||
|
||||
public void testDontExplode() throws Exception {
|
||||
assertAcked(prepareCreate("index1")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child", "_parent", "type=parent"));
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("index1", "parent", "1").setSource("{}", XContentType.JSON));
|
||||
requests.add(client().prepareIndex("index1", "child", "1").setParent("1").setSource("field", "value1"));
|
||||
indexRandom(true, requests);
|
||||
|
||||
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value1"), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
|
||||
SearchResponse response = client().prepareSearch("index1")
|
||||
.setQuery(query)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
|
||||
assertAcked(prepareCreate("index2").addMapping("type", "nested", "type=nested"));
|
||||
client().prepareIndex("index2", "type", "1").setSource(jsonBuilder().startObject()
|
||||
.startArray("nested")
|
||||
.startObject()
|
||||
.field("field", "value1")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject())
|
||||
.setRefreshPolicy(IMMEDIATE)
|
||||
.get();
|
||||
|
||||
query = nestedQuery("nested", matchQuery("nested.field", "value1"), ScoreMode.Avg)
|
||||
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
|
||||
response = client().prepareSearch("index2")
|
||||
.setQuery(query)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 1);
|
||||
}
|
||||
|
||||
public void testNestedInnerHitWrappedInParentChildInnerhit() throws Exception {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("child_type", "_parent", "type=parent_type", "nested_type", "type=nested"));
|
||||
client().prepareIndex("test", "parent_type", "1").setSource("key", "value").get();
|
||||
client().prepareIndex("test", "child_type", "2").setParent("1").setSource("nested_type", Collections.singletonMap("key", "value"))
|
||||
.get();
|
||||
refresh();
|
||||
SearchResponse response = client().prepareSearch("test")
|
||||
.setQuery(boolQuery().must(matchQuery("key", "value"))
|
||||
.should(hasChildQuery("child_type", nestedQuery("nested_type", matchAllQuery(), ScoreMode.None)
|
||||
.innerHit(new InnerHitBuilder(), false), ScoreMode.None).innerHit(new InnerHitBuilder(), false)))
|
||||
.get();
|
||||
assertHitCount(response, 1);
|
||||
SearchHit hit = response.getHits().getAt(0);
|
||||
assertThat(hit.getInnerHits().get("child_type").getAt(0).field("_parent").getValue(), equalTo("1"));
|
||||
assertThat(hit.getInnerHits().get("child_type").getAt(0).getInnerHits().get("nested_type").getAt(0).field("_parent"), nullValue());
|
||||
}
|
||||
|
||||
public void testInnerHitsWithIgnoreUnmapped() throws Exception {
|
||||
assertAcked(prepareCreate("index1")
|
||||
.setSettings("index.mapping.single_type", false)
|
||||
.addMapping("parent_type", "nested_type", "type=nested")
|
||||
.addMapping("child_type", "_parent", "type=parent_type")
|
||||
);
|
||||
createIndex("index2");
|
||||
client().prepareIndex("index1", "parent_type", "1").setSource("nested_type", Collections.singletonMap("key", "value")).get();
|
||||
client().prepareIndex("index1", "child_type", "2").setParent("1").setSource("{}", XContentType.JSON).get();
|
||||
client().prepareIndex("index2", "type", "3").setSource("key", "value").get();
|
||||
refresh();
|
||||
|
||||
SearchResponse response = client().prepareSearch("index1", "index2")
|
||||
.setQuery(boolQuery()
|
||||
.should(hasChildQuery("child_type", matchAllQuery(), ScoreMode.None).ignoreUnmapped(true)
|
||||
.innerHit(new InnerHitBuilder(), true))
|
||||
.should(termQuery("key", "value"))
|
||||
)
|
||||
.get();
|
||||
assertNoFailures(response);
|
||||
assertHitCount(response, 2);
|
||||
assertSearchHits(response, "1", "3");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
body:
|
||||
settings:
|
||||
mapping.single_type: false
|
||||
mappings:
|
||||
type_2: {}
|
||||
type_3:
|
||||
_parent:
|
||||
type: type_2
|
||||
|
||||
---
|
||||
"Parent/child inner hits":
|
||||
- skip:
|
||||
version: " - 5.99.99"
|
||||
reason: mapping.single_type was added in 6.0
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: type_2
|
||||
id: 1
|
||||
body: {"foo": "bar"}
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: type_3
|
||||
id: 1
|
||||
parent: 1
|
||||
body: {"bar": "baz"}
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query" : { "has_child" : { "type" : "type_3", "query" : { "match_all" : {} }, "inner_hits" : {} } } }
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._index: "test" }
|
||||
- match: { hits.hits.0._type: "type_2" }
|
||||
- match: { hits.hits.0._id: "1" }
|
||||
- is_false: hits.hits.0.inner_hits.type_3.hits.hits.0._index
|
||||
- match: { hits.hits.0.inner_hits.type_3.hits.hits.0._type: "type_3" }
|
||||
- match: { hits.hits.0.inner_hits.type_3.hits.hits.0._id: "1" }
|
||||
- is_false: hits.hits.0.inner_hits.type_3.hits.hits.0._nested
|
|
@ -23,5 +23,9 @@ esplugin {
|
|||
hasClientJar = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// for testing hasChild and hasParent rejections
|
||||
testCompile project(path: ':modules:parent-join', configuration: 'runtime')
|
||||
}
|
||||
compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes"
|
||||
compileTestJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes"
|
||||
|
|
|
@ -57,8 +57,6 @@ import org.elasticsearch.index.query.BoolQueryBuilder;
|
|||
import org.elasticsearch.index.query.BoostingQueryBuilder;
|
||||
import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
|
||||
import org.elasticsearch.index.query.DisMaxQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
|
@ -372,15 +370,16 @@ public class PercolatorFieldMapper extends FieldMapper {
|
|||
return CONTENT_TYPE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fails if a percolator contains an unsupported query. The following queries are not supported:
|
||||
* 1) a has_child query
|
||||
* 2) a has_parent query
|
||||
*/
|
||||
static void verifyQuery(QueryBuilder queryBuilder) {
|
||||
if (queryBuilder instanceof HasChildQueryBuilder) {
|
||||
if (queryBuilder.getName().equals("has_child")) {
|
||||
throw new IllegalArgumentException("the [has_child] query is unsupported inside a percolator query");
|
||||
} else if (queryBuilder instanceof HasParentQueryBuilder) {
|
||||
} else if (queryBuilder.getName().equals("has_parent")) {
|
||||
throw new IllegalArgumentException("the [has_parent] query is unsupported inside a percolator query");
|
||||
} else if (queryBuilder instanceof BoolQueryBuilder) {
|
||||
BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) queryBuilder;
|
||||
|
|
|
@ -52,13 +52,10 @@ import org.elasticsearch.index.mapper.MapperService;
|
|||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||
import org.elasticsearch.index.mapper.SourceToParse;
|
||||
import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.BoostingQueryBuilder;
|
||||
import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
|
||||
import org.elasticsearch.index.query.DisMaxQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
@ -67,6 +64,9 @@ import org.elasticsearch.index.query.RangeQueryBuilder;
|
|||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.RandomScoreFunctionBuilder;
|
||||
import org.elasticsearch.indices.TermsLookup;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.join.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.join.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.script.Script;
|
||||
|
@ -109,7 +109,7 @@ public class PercolatorFieldMapperTests extends ESSingleNodeTestCase {
|
|||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> getPlugins() {
|
||||
return pluginList(InternalSettingsPlugin.class, PercolatorPlugin.class, FoolMeScriptPlugin.class);
|
||||
return pluginList(InternalSettingsPlugin.class, PercolatorPlugin.class, FoolMeScriptPlugin.class, ParentJoinPlugin.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
@ -39,6 +39,8 @@ dependencies {
|
|||
compile "org.elasticsearch.client:rest:${version}"
|
||||
// for http - testing reindex from remote
|
||||
testCompile project(path: ':modules:transport-netty4', configuration: 'runtime')
|
||||
// for parent/child testing
|
||||
testCompile project(path: ':modules:parent-join', configuration: 'runtime')
|
||||
}
|
||||
|
||||
dependencyLicenses {
|
||||
|
|
|
@ -22,9 +22,16 @@ package org.elasticsearch.index.reindex;
|
|||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.idsQuery;
|
||||
import static org.elasticsearch.join.query.JoinQueryBuilders.hasParentQuery;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -40,6 +47,23 @@ public class ReindexParentChildTests extends ReindexTestCase {
|
|||
QueryBuilder findsCity;
|
||||
QueryBuilder findsNeighborhood;
|
||||
|
||||
@Override
|
||||
protected boolean ignoreExternalCluster() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
final List<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
|
||||
plugins.add(ParentJoinPlugin.class);
|
||||
return Collections.unmodifiableList(plugins);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
|
||||
return nodePlugins();
|
||||
}
|
||||
|
||||
public void testParentChild() throws Exception {
|
||||
createParentChildIndex("source");
|
||||
createParentChildIndex("dest");
|
||||
|
|
|
@ -158,85 +158,6 @@
|
|||
metric: search
|
||||
- match: {indices.source.total.search.open_contexts: 0}
|
||||
|
||||
---
|
||||
"Reindex from remote with parent/child":
|
||||
- do:
|
||||
indices.create:
|
||||
index: source
|
||||
body:
|
||||
settings:
|
||||
mapping.single_type: false
|
||||
mappings:
|
||||
foo: {}
|
||||
bar:
|
||||
_parent:
|
||||
type: foo
|
||||
- do:
|
||||
indices.create:
|
||||
index: dest
|
||||
body:
|
||||
settings:
|
||||
mapping.single_type: false
|
||||
mappings:
|
||||
foo: {}
|
||||
bar:
|
||||
_parent:
|
||||
type: foo
|
||||
- do:
|
||||
index:
|
||||
index: source
|
||||
type: foo
|
||||
id: 1
|
||||
body: { "text": "test" }
|
||||
- do:
|
||||
index:
|
||||
index: source
|
||||
type: bar
|
||||
id: 1
|
||||
parent: 1
|
||||
body: { "text": "test2" }
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
# Fetch the http host. We use the host of the master because we know there will always be a master.
|
||||
- do:
|
||||
cluster.state: {}
|
||||
- set: { master_node: master }
|
||||
- do:
|
||||
nodes.info:
|
||||
metric: [ http ]
|
||||
- is_true: nodes.$master.http.publish_address
|
||||
- set: {nodes.$master.http.publish_address: host}
|
||||
- do:
|
||||
reindex:
|
||||
refresh: true
|
||||
body:
|
||||
source:
|
||||
remote:
|
||||
host: http://${host}
|
||||
index: source
|
||||
dest:
|
||||
index: dest
|
||||
- match: {created: 2}
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: dest
|
||||
body:
|
||||
query:
|
||||
has_parent:
|
||||
parent_type: foo
|
||||
query:
|
||||
match:
|
||||
text: test
|
||||
- match: {hits.total: 1}
|
||||
|
||||
# Make sure reindex closed all the scroll contexts
|
||||
- do:
|
||||
indices.stats:
|
||||
index: source
|
||||
metric: search
|
||||
- match: {indices.source.total.search.open_contexts: 0}
|
||||
|
||||
---
|
||||
"Reindex from remote with timeouts":
|
||||
|
|
|
@ -22,4 +22,6 @@ apply plugin: 'elasticsearch.rest-test'
|
|||
|
||||
integTestCluster {
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
}
|
||||
// Whitelist reindexing from the local node so we can test it.
|
||||
setting 'reindex.remote.whitelist', '127.0.0.1:*'
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
"Reindex from remote with parent/child":
|
||||
- do:
|
||||
indices.create:
|
||||
index: source
|
||||
body:
|
||||
settings:
|
||||
mapping.single_type: false
|
||||
mappings:
|
||||
foo: {}
|
||||
bar:
|
||||
_parent:
|
||||
type: foo
|
||||
- do:
|
||||
indices.create:
|
||||
index: dest
|
||||
body:
|
||||
settings:
|
||||
mapping.single_type: false
|
||||
mappings:
|
||||
foo: {}
|
||||
bar:
|
||||
_parent:
|
||||
type: foo
|
||||
- do:
|
||||
index:
|
||||
index: source
|
||||
type: foo
|
||||
id: 1
|
||||
body: { "text": "test" }
|
||||
- do:
|
||||
index:
|
||||
index: source
|
||||
type: bar
|
||||
id: 1
|
||||
parent: 1
|
||||
body: { "text": "test2" }
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
# Fetch the http host. We use the host of the master because we know there will always be a master.
|
||||
- do:
|
||||
cluster.state: {}
|
||||
- set: { master_node: master }
|
||||
- do:
|
||||
nodes.info:
|
||||
metric: [ http ]
|
||||
- is_true: nodes.$master.http.publish_address
|
||||
- set: {nodes.$master.http.publish_address: host}
|
||||
- do:
|
||||
reindex:
|
||||
refresh: true
|
||||
body:
|
||||
source:
|
||||
remote:
|
||||
host: http://${host}
|
||||
index: source
|
||||
dest:
|
||||
index: dest
|
||||
- match: {created: 2}
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: dest
|
||||
body:
|
||||
query:
|
||||
has_parent:
|
||||
parent_type: foo
|
||||
query:
|
||||
match:
|
||||
text: test
|
||||
- match: {hits.total: 1}
|
||||
|
||||
# Make sure reindex closed all the scroll contexts
|
||||
- do:
|
||||
indices.stats:
|
||||
index: source
|
||||
metric: search
|
||||
- match: {indices.source.total.search.open_contexts: 0}
|
|
@ -11,10 +11,6 @@ setup:
|
|||
properties:
|
||||
nested_field:
|
||||
type: nested
|
||||
type_2: {}
|
||||
type_3:
|
||||
_parent:
|
||||
type: type_2
|
||||
|
||||
---
|
||||
"Nested inner hits":
|
||||
|
@ -47,38 +43,3 @@ setup:
|
|||
- match: { hits.hits.0.inner_hits.nested_field.hits.hits.0._nested.offset: 0 }
|
||||
- is_false: hits.hits.0.inner_hits.nested_field.hits.hits.0._nested.child
|
||||
|
||||
---
|
||||
"Parent/child inner hits":
|
||||
- skip:
|
||||
version: " - 5.99.99"
|
||||
reason: mapping.single_type was added in 6.0
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: type_2
|
||||
id: 1
|
||||
body: {"foo": "bar"}
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: type_3
|
||||
id: 1
|
||||
parent: 1
|
||||
body: {"bar": "baz"}
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
body: { "query" : { "has_child" : { "type" : "type_3", "query" : { "match_all" : {} }, "inner_hits" : {} } } }
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._index: "test" }
|
||||
- match: { hits.hits.0._type: "type_2" }
|
||||
- match: { hits.hits.0._id: "1" }
|
||||
- is_false: hits.hits.0.inner_hits.type_3.hits.hits.0._index
|
||||
- match: { hits.hits.0.inner_hits.type_3.hits.hits.0._type: "type_3" }
|
||||
- match: { hits.hits.0.inner_hits.type_3.hits.hits.0._id: "1" }
|
||||
- is_false: hits.hits.0.inner_hits.type_3.hits.hits.0._nested
|
||||
|
|
|
@ -34,6 +34,7 @@ List projects = [
|
|||
'modules:lang-expression',
|
||||
'modules:lang-mustache',
|
||||
'modules:lang-painless',
|
||||
'modules:parent-join',
|
||||
'modules:percolator',
|
||||
'modules:reindex',
|
||||
'modules:repository-url',
|
||||
|
@ -72,7 +73,7 @@ List projects = [
|
|||
'qa:smoke-test-ingest-disabled',
|
||||
'qa:smoke-test-multinode',
|
||||
'qa:smoke-test-plugins',
|
||||
'qa:smoke-test-reindex-with-painless',
|
||||
'qa:smoke-test-reindex-with-all-modules',
|
||||
'qa:smoke-test-tribe-node',
|
||||
'qa:vagrant',
|
||||
'qa:wildfly'
|
||||
|
|
|
@ -33,6 +33,9 @@ import org.elasticsearch.common.xcontent.XContentType;
|
|||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.indices.IndicesModule;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.plugins.PluginsService;
|
||||
import org.elasticsearch.plugins.SearchPlugin;
|
||||
import org.elasticsearch.search.SearchModule;
|
||||
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
|
||||
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||
|
@ -40,6 +43,7 @@ import org.elasticsearch.test.ESTestCase;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -66,6 +70,10 @@ public abstract class BaseAggregationTestCase<AB extends AbstractAggregationBuil
|
|||
private NamedXContentRegistry xContentRegistry;
|
||||
protected abstract AB createTestAggregatorBuilder();
|
||||
|
||||
protected Collection<Class<? extends Plugin>> getPlugins() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup for the whole base test class.
|
||||
*/
|
||||
|
@ -77,7 +85,8 @@ public abstract class BaseAggregationTestCase<AB extends AbstractAggregationBuil
|
|||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
|
||||
.build();
|
||||
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
|
||||
SearchModule searchModule = new SearchModule(settings, false, emptyList());
|
||||
PluginsService pluginsService = new PluginsService(settings, null, null, getPlugins());
|
||||
SearchModule searchModule = new SearchModule(settings, false, pluginsService.filterPlugins(SearchPlugin.class));
|
||||
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
|
||||
entries.addAll(indicesModule.getNamedWriteables());
|
||||
entries.addAll(searchModule.getNamedWriteables());
|
||||
|
@ -145,7 +154,6 @@ public abstract class BaseAggregationTestCase<AB extends AbstractAggregationBuil
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void testEqualsAndHashcode() throws IOException {
|
||||
// TODO we only change name and boost, we should extend by any sub-test supplying a "mutate" method that randomly changes one
|
||||
// aspect of the object under test
|
|
@ -17,10 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.search.aggregations.bucket;
|
||||
package org.elasticsearch.search.aggregations;
|
||||
|
||||
import org.elasticsearch.search.aggregations.InternalAggregation;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||
import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregation;
|
||||
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
|
||||
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
Loading…
Reference in New Issue