diff --git a/build.gradle b/build.gradle
index 09748ea1e8afb..615a63b2d37bf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,6 +13,7 @@
* 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
+ * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@@ -138,6 +139,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 {
diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index 9a550740fde36..4acd927fff1d9 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -620,7 +620,6 @@
-
@@ -689,7 +688,6 @@
-
@@ -716,7 +714,6 @@
-
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/QueryDSLDocumentationTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/QueryDSLDocumentationTests.java
index f01e4824b3fa3..f48572b047382 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/QueryDSLDocumentationTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/QueryDSLDocumentationTests.java
@@ -51,8 +51,6 @@
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 void testGeoShape() throws IOException {
}
}
- 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")
diff --git a/client/transport/build.gradle b/client/transport/build.gradle
index 77833c1f2672d..b2edc9c8fcd8f 100644
--- a/client/transport/build.gradle
+++ b/client/transport/build.gradle
@@ -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}"
diff --git a/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java b/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java
index c1b240066abe2..83a9ac544c65d 100644
--- a/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java
+++ b/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java
@@ -195,7 +195,8 @@ private InnerHitBuilder(InnerHitBuilder other) {
}
}
- InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType, boolean ignoreUnmapped) {
+ // TODO public for hasChild and hasParent query.
+ public InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType, boolean ignoreUnmapped) {
this(other);
this.query = query;
this.parentChildType = parentChildType;
@@ -751,7 +752,8 @@ public static void extractInnerHits(QueryBuilder query, Map plugins) {
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 @@ private void registerQueryParsers(List plugins) {
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));
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java b/core/src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java
index f43c2670abdb4..8b704ee8a69a2 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java
+++ b/core/src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java
@@ -23,8 +23,6 @@
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 static FiltersAggregationBuilder filters(String name, KeyedFilter... filt
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 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 filters) {
return new AdjacencyMatrixAggregationBuilder(name, separator, filters);
- }
+ }
/**
* Create a new {@link Sampler} aggregation with the given name.
@@ -220,13 +218,6 @@ public static ReverseNestedAggregationBuilder reverseNested(String name) {
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.
*/
diff --git a/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/CustomQueryScorer.java b/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/CustomQueryScorer.java
index e25e7b74941d7..2f728e21b6f34 100644
--- a/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/CustomQueryScorer.java
+++ b/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/CustomQueryScorer.java
@@ -26,7 +26,6 @@
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 @@ protected void extractUnknownQuery(Query query,
}
protected void extract(Query query, float boost, Map 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 @@ protected void extract(Query query, float boost, Map t
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);
+ }
}
}
diff --git a/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java b/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
index 21930b3763b6a..cf41042ab8c78 100644
--- a/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
+++ b/core/src/test/java/org/elasticsearch/action/bulk/BulkWithUpdatesIT.java
@@ -450,156 +450,7 @@ public void testBulkIndexingWhileInitializing() throws Exception {
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
diff --git a/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java b/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java
index 711804153cf1e..e711117fb6ec7 100644
--- a/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java
+++ b/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java
@@ -63,8 +63,6 @@
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 void testAliasFilterWithNowInRangeFilterAndQuery() throws Exception {
}
}
- 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();
diff --git a/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java
index 6de9cbab62071..a3f61eab35a51 100644
--- a/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java
+++ b/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java
@@ -152,24 +152,6 @@ public void testInlineLeafInnerHitsNestedQuery() throws Exception {
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 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 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)
@@ -180,25 +162,6 @@ public void testInlineLeafInnerHitsNestedQueryViaBoolQuery() {
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 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)
@@ -251,43 +214,6 @@ public void testBuildIgnoreUnmappedNestQuery() throws Exception {
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);
}
diff --git a/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
index 267963878ea16..ed4fbcd53cdc6 100644
--- a/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
+++ b/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
@@ -61,7 +61,7 @@ protected void initializeAdditionalMappings(MapperService mapperService) throws
}
/**
- * @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 void testIgnoreUnmappedWithRewrite() throws IOException {
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());
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java b/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java
index 8514096b83763..96767c99b9daa 100644
--- a/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java
+++ b/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java
@@ -270,8 +270,6 @@ public List getPipelineAggregations() {
"geo_distance",
"geo_polygon",
"geo_shape",
- "has_child",
- "has_parent",
"ids",
"match",
"match_all",
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/filter/InternalFilterTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/filter/InternalFilterTests.java
index 3e74b9c21877e..464f081f6c984 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/filter/InternalFilterTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/filter/InternalFilterTests.java
@@ -21,7 +21,7 @@
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;
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/global/InternalGlobalTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/global/InternalGlobalTests.java
index 9092c3e028079..2a284746bf612 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/global/InternalGlobalTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/global/InternalGlobalTests.java
@@ -21,7 +21,7 @@
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;
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/missing/InternalMissingTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/missing/InternalMissingTests.java
index f3e151721bf30..1a702e94024cc 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/missing/InternalMissingTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/missing/InternalMissingTests.java
@@ -21,7 +21,7 @@
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;
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalNestedTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalNestedTests.java
index 7b410723666d4..a330c8a146e34 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalNestedTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalNestedTests.java
@@ -21,7 +21,7 @@
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;
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalReverseNestedTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalReverseNestedTests.java
index f918024733e3a..069ac03829552 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalReverseNestedTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/InternalReverseNestedTests.java
@@ -21,7 +21,7 @@
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;
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSamplerTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSamplerTests.java
index 1c4fb6d2a65f7..23facaf8fd25e 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSamplerTests.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/InternalSamplerTests.java
@@ -20,7 +20,7 @@
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 @@ protected void extraAssertReduced(InternalSampler reduced, List
protected Writeable.Reader instanceReader() {
return InternalSampler::new;
}
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/org/elasticsearch/search/fetch/subphase/InnerHitsIT.java b/core/src/test/java/org/elasticsearch/search/fetch/subphase/InnerHitsIT.java
index 6fbda92ba2699..8eca50556460c 100644
--- a/core/src/test/java/org/elasticsearch/search/fetch/subphase/InnerHitsIT.java
+++ b/core/src/test/java/org/elasticsearch/search/fetch/subphase/InnerHitsIT.java
@@ -55,8 +55,6 @@
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 void testRandomNested() throws Exception {
}
}
- 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 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("fox 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 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 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 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 void testInnerHitsWithObjectFieldThatHasANestedField() throws Exception {
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 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 void testMatchesQueriesNestedInnerHits() throws Exception {
}
}
- public void testMatchesQueriesParentChildInnerHits() throws Exception {
- assertAcked(prepareCreate("index")
- .setSettings("index.mapping.single_type", false)
- .addMapping("child", "_parent", "type=parent"));
- List 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 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 void testNestedSourceFiltering() throws Exception {
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 void testInnerHitsWithIgnoreUnmapped() throws Exception {
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");
}
}
diff --git a/docs/java-api/aggregations/bucket/children-aggregation.asciidoc b/docs/java-api/aggregations/bucket/children-aggregation.asciidoc
index 1bf8a5b26e69e..f6a23fdafe976 100644
--- a/docs/java-api/aggregations/bucket/children-aggregation.asciidoc
+++ b/docs/java-api/aggregations/bucket/children-aggregation.asciidoc
@@ -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]
diff --git a/modules/parent-join/build.gradle b/modules/parent-join/build.gradle
new file mode 100644
index 0000000000000..67bcc9d54e8e7
--- /dev/null
+++ b/modules/parent-join/build.gradle
@@ -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
+}
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/ParentJoinPlugin.java b/modules/parent-join/src/main/java/org/elasticsearch/join/ParentJoinPlugin.java
new file mode 100644
index 0000000000000..cef46f54ab7ab
--- /dev/null
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/ParentJoinPlugin.java
@@ -0,0 +1,58 @@
+/*
+ * 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 {
+ private final Settings settings;
+
+ public ParentJoinPlugin(Settings settings) {
+ this.settings = settings;
+ }
+
+ @Override
+ public List> getQueries() {
+ return Arrays.asList(
+ new QuerySpec<>(HasChildQueryBuilder.NAME, HasChildQueryBuilder::new, HasChildQueryBuilder::fromXContent),
+ new QuerySpec<>(HasParentQueryBuilder.NAME, HasParentQueryBuilder::new, HasParentQueryBuilder::fromXContent)
+ );
+ }
+
+ @Override
+ public List getAggregations() {
+ return Collections.singletonList(
+ new AggregationSpec(ChildrenAggregationBuilder.NAME, ChildrenAggregationBuilder::new, ChildrenAggregationBuilder::parse)
+ .addResultReader(InternalChildren::new)
+ );
+ }
+
+
+}
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/Children.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/Children.java
similarity index 94%
rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/Children.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/Children.java
index b1e4b2877a3a0..394c690709d8a 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/Children.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/Children.java
@@ -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;
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregationBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
similarity index 99%
rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregationBuilder.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
index 3a0d2fff982d8..d04b1f0a66052 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregationBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java
@@ -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;
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregatorFactory.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregatorFactory.java
similarity index 98%
rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregatorFactory.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregatorFactory.java
index b0a4c64305aa1..800be74ba6fe6 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ChildrenAggregatorFactory.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregatorFactory.java
@@ -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;
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildren.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/InternalChildren.java
similarity index 97%
rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildren.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/InternalChildren.java
index 05a38c8cd59b5..05cd40e3d3366 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildren.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/InternalChildren.java
@@ -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;
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/JoinAggregationBuilders.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/JoinAggregationBuilders.java
new file mode 100644
index 0000000000000..73522a68b4595
--- /dev/null
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/JoinAggregationBuilders.java
@@ -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);
+ }
+}
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregator.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregator.java
similarity index 99%
rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregator.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregator.java
index 37a443e9bab34..c1ffb097abc39 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregator.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ParentToChildrenAggregator.java
@@ -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;
diff --git a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
similarity index 94%
rename from core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
index 18ad7f9f310b5..494c5e498e13b 100644
--- a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java
@@ -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.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 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep
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 static HasChildQueryBuilder fromXContent(QueryParseContext parseContext)
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 static HasChildQueryBuilder fromXContent(QueryParseContext parseContext)
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;
diff --git a/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
similarity index 96%
rename from core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java
rename to modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
index 63c9484691766..ca0bfd623d51b 100644
--- a/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java
@@ -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.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;
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/query/JoinQueryBuilders.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/JoinQueryBuilders.java
new file mode 100644
index 0000000000000..af778f400f7b3
--- /dev/null
+++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/JoinQueryBuilders.java
@@ -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);
+ }
+
+}
diff --git a/modules/parent-join/src/test/java/org/elasticsearch/join/ParentChildClientYamlTestSuiteIT.java b/modules/parent-join/src/test/java/org/elasticsearch/join/ParentChildClientYamlTestSuiteIT.java
new file mode 100644
index 0000000000000..666fa736d45de
--- /dev/null
+++ b/modules/parent-join/src/test/java/org/elasticsearch/join/ParentChildClientYamlTestSuiteIT.java
@@ -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