From 279a18a527b9c23b06c8b75c2aa9321aefca9728 Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Fri, 12 May 2017 15:58:06 +0200 Subject: 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 --- .../search/aggregations/bucket/ChildrenIT.java | 472 --------------------- .../search/aggregations/bucket/ChildrenTests.java | 35 -- .../InternalSingleBucketAggregationTestCase.java | 80 ---- .../bucket/children/InternalChildrenTests.java | 47 -- .../children/ParentToChildrenAggregatorTests.java | 190 --------- .../bucket/filter/InternalFilterTests.java | 2 +- .../bucket/global/InternalGlobalTests.java | 2 +- .../bucket/missing/InternalMissingTests.java | 2 +- .../bucket/nested/InternalNestedTests.java | 2 +- .../bucket/nested/InternalReverseNestedTests.java | 2 +- .../bucket/sampler/InternalSamplerTests.java | 4 +- 11 files changed, 7 insertions(+), 831 deletions(-) delete mode 100644 core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenIT.java delete mode 100644 core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenTests.java delete mode 100644 core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java delete mode 100644 core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildrenTests.java delete mode 100644 core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregatorTests.java (limited to 'core/src/test/java/org/elasticsearch/search/aggregations/bucket') diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenIT.java deleted file mode 100644 index bfe483ca89..0000000000 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenIT.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * 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.search.aggregations.bucket; - -import org.apache.lucene.search.join.ScoreMode; -import org.elasticsearch.action.index.IndexRequestBuilder; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.action.update.UpdateResponse; -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.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 java.util.ArrayList; -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.search.aggregations.AggregationBuilders.sum; -import static org.elasticsearch.search.aggregations.AggregationBuilders.terms; -import static org.elasticsearch.search.aggregations.AggregationBuilders.topHits; -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.assertSearchResponse; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.sameInstance; - -@ESIntegTestCase.SuiteScopeTestCase -public class ChildrenIT extends ESIntegTestCase { - - private static final Map categoryToControl = new HashMap<>(); - - @Override - public void setupSuiteScopeCluster() throws Exception { - assertAcked( - prepareCreate("test") - .setSettings("index.mapping.single_type", false) - .addMapping("article", "category", "type=keyword") - .addMapping("comment", "_parent", "type=article", "commenter", "type=keyword") - ); - - List requests = new ArrayList<>(); - String[] uniqueCategories = new String[randomIntBetween(1, 25)]; - for (int i = 0; i < uniqueCategories.length; i++) { - uniqueCategories[i] = Integer.toString(i); - } - int catIndex = 0; - - int numParentDocs = randomIntBetween(uniqueCategories.length, uniqueCategories.length * 5); - for (int i = 0; i < numParentDocs; i++) { - String id = Integer.toString(i); - - // TODO: this array is always of length 1, and testChildrenAggs fails if this is changed - String[] categories = new String[randomIntBetween(1,1)]; - for (int j = 0; j < categories.length; j++) { - String category = categories[j] = uniqueCategories[catIndex++ % uniqueCategories.length]; - Control control = categoryToControl.get(category); - if (control == null) { - categoryToControl.put(category, control = new Control(category)); - } - control.articleIds.add(id); - } - - requests.add(client().prepareIndex("test", "article", id).setCreate(true).setSource("category", categories, "randomized", true)); - } - - String[] commenters = new String[randomIntBetween(5, 50)]; - for (int i = 0; i < commenters.length; i++) { - commenters[i] = Integer.toString(i); - } - - int id = 0; - for (Control control : categoryToControl.values()) { - for (String articleId : control.articleIds) { - int numChildDocsPerParent = randomIntBetween(0, 5); - for (int i = 0; i < numChildDocsPerParent; i++) { - String commenter = commenters[id % commenters.length]; - String idValue = Integer.toString(id++); - control.commentIds.add(idValue); - Set ids = control.commenterToCommentId.get(commenter); - if (ids == null) { - 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", "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"); - } - - public void testChildrenAggs() throws Exception { - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(matchQuery("randomized", true)) - .addAggregation( - terms("category").field("category").size(10000).subAggregation(children("to_comment", "comment") - .subAggregation( - terms("commenters").field("commenter").size(10000).subAggregation( - topHits("top_comments") - )) - ) - ).get(); - assertSearchResponse(searchResponse); - - Terms categoryTerms = searchResponse.getAggregations().get("category"); - assertThat(categoryTerms.getBuckets().size(), equalTo(categoryToControl.size())); - for (Map.Entry entry1 : categoryToControl.entrySet()) { - Terms.Bucket categoryBucket = categoryTerms.getBucketByKey(entry1.getKey()); - assertThat(categoryBucket.getKeyAsString(), equalTo(entry1.getKey())); - assertThat(categoryBucket.getDocCount(), equalTo((long) entry1.getValue().articleIds.size())); - - 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())); - - Terms commentersTerms = childrenBucket.getAggregations().get("commenters"); - assertThat((Terms) ((InternalAggregation)childrenBucket).getProperty("commenters"), sameInstance(commentersTerms)); - assertThat(commentersTerms.getBuckets().size(), equalTo(entry1.getValue().commenterToCommentId.size())); - for (Map.Entry> entry2 : entry1.getValue().commenterToCommentId.entrySet()) { - Terms.Bucket commentBucket = commentersTerms.getBucketByKey(entry2.getKey()); - assertThat(commentBucket.getKeyAsString(), equalTo(entry2.getKey())); - assertThat(commentBucket.getDocCount(), equalTo((long) entry2.getValue().size())); - - TopHits topHits = commentBucket.getAggregations().get("top_comments"); - for (SearchHit searchHit : topHits.getHits().getHits()) { - assertThat(entry2.getValue().contains(searchHit.getId()), is(true)); - } - } - } - } - - public void testParentWithMultipleBuckets() throws Exception { - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(matchQuery("randomized", false)) - .addAggregation( - terms("category").field("category").size(10000).subAggregation( - children("to_comment", "comment").subAggregation(topHits("top_comments").sort("_uid", SortOrder.ASC)) - ) - ).get(); - assertSearchResponse(searchResponse); - - Terms categoryTerms = searchResponse.getAggregations().get("category"); - assertThat(categoryTerms.getBuckets().size(), equalTo(3)); - - for (Terms.Bucket bucket : categoryTerms.getBuckets()) { - logger.info("bucket={}", bucket.getKey()); - Children childrenBucket = bucket.getAggregations().get("to_comment"); - TopHits topHits = childrenBucket.getAggregations().get("top_comments"); - logger.info("total_hits={}", topHits.getHits().getTotalHits()); - for (SearchHit searchHit : topHits.getHits()) { - logger.info("hit= {} {} {}", searchHit.getSortValues()[0], searchHit.getType(), searchHit.getId()); - } - } - - Terms.Bucket categoryBucket = categoryTerms.getBucketByKey("a"); - assertThat(categoryBucket.getKeyAsString(), equalTo("a")); - assertThat(categoryBucket.getDocCount(), equalTo(3L)); - - Children childrenBucket = categoryBucket.getAggregations().get("to_comment"); - assertThat(childrenBucket.getName(), equalTo("to_comment")); - assertThat(childrenBucket.getDocCount(), equalTo(2L)); - TopHits topHits = childrenBucket.getAggregations().get("top_comments"); - assertThat(topHits.getHits().getTotalHits(), equalTo(2L)); - assertThat(topHits.getHits().getAt(0).getId(), equalTo("a")); - assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment")); - assertThat(topHits.getHits().getAt(1).getId(), equalTo("c")); - assertThat(topHits.getHits().getAt(1).getType(), equalTo("comment")); - - categoryBucket = categoryTerms.getBucketByKey("b"); - assertThat(categoryBucket.getKeyAsString(), equalTo("b")); - assertThat(categoryBucket.getDocCount(), equalTo(2L)); - - childrenBucket = categoryBucket.getAggregations().get("to_comment"); - assertThat(childrenBucket.getName(), equalTo("to_comment")); - assertThat(childrenBucket.getDocCount(), equalTo(1L)); - topHits = childrenBucket.getAggregations().get("top_comments"); - assertThat(topHits.getHits().getTotalHits(), equalTo(1L)); - assertThat(topHits.getHits().getAt(0).getId(), equalTo("c")); - assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment")); - - categoryBucket = categoryTerms.getBucketByKey("c"); - assertThat(categoryBucket.getKeyAsString(), equalTo("c")); - assertThat(categoryBucket.getDocCount(), equalTo(2L)); - - childrenBucket = categoryBucket.getAggregations().get("to_comment"); - assertThat(childrenBucket.getName(), equalTo("to_comment")); - assertThat(childrenBucket.getDocCount(), equalTo(1L)); - topHits = childrenBucket.getAggregations().get("top_comments"); - assertThat(topHits.getHits().getTotalHits(), equalTo(1L)); - assertThat(topHits.getHits().getAt(0).getId(), equalTo("c")); - assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment")); - } - - public void testWithDeletes() throws Exception { - String indexName = "xyz"; - assertAcked( - prepareCreate(indexName) - .setSettings("index.mapping.single_type", false) - .addMapping("parent") - .addMapping("child", "_parent", "type=parent", "count", "type=long") - ); - - List requests = new ArrayList<>(); - requests.add(client().prepareIndex(indexName, "parent", "1").setSource("{}", XContentType.JSON)); - requests.add(client().prepareIndex(indexName, "child", "0").setParent("1").setSource("count", 1)); - requests.add(client().prepareIndex(indexName, "child", "1").setParent("1").setSource("count", 1)); - requests.add(client().prepareIndex(indexName, "child", "2").setParent("1").setSource("count", 1)); - requests.add(client().prepareIndex(indexName, "child", "3").setParent("1").setSource("count", 1)); - indexRandom(true, requests); - - for (int i = 0; i < 10; i++) { - SearchResponse searchResponse = client().prepareSearch(indexName) - .addAggregation(children("children", "child").subAggregation(sum("counts").field("count"))) - .get(); - - assertNoFailures(searchResponse); - Children children = searchResponse.getAggregations().get("children"); - assertThat(children.getDocCount(), equalTo(4L)); - - Sum count = children.getAggregations().get("counts"); - assertThat(count.getValue(), equalTo(4.)); - - String idToUpdate = Integer.toString(randomInt(3)); - /* - * The whole point of this test is to test these things with deleted - * docs in the index so we turn off detect_noop to make sure that - * the updates cause that. - */ - UpdateResponse updateResponse = client().prepareUpdate(indexName, "child", idToUpdate) - .setParent("1") - .setDoc(Requests.INDEX_CONTENT_TYPE, "count", 1) - .setDetectNoop(false) - .get(); - assertThat(updateResponse.getVersion(), greaterThan(1L)); - refresh(); - } - } - - public void testNonExistingChildType() throws Exception { - SearchResponse searchResponse = client().prepareSearch("test") - .addAggregation( -children("non-existing", "xyz") - ).get(); - assertSearchResponse(searchResponse); - - Children children = searchResponse.getAggregations().get("non-existing"); - assertThat(children.getName(), equalTo("non-existing")); - assertThat(children.getDocCount(), equalTo(0L)); - } - - public void testPostCollection() throws Exception { - String indexName = "prodcatalog"; - String masterType = "masterprod"; - String childType = "variantsku"; - assertAcked( - prepareCreate(indexName) - .setSettings("index.mapping.single_type", false) - .addMapping(masterType, "brand", "type=text", "name", "type=keyword", "material", "type=text") - .addMapping(childType, "_parent", "type=masterprod", "color", "type=keyword", "size", "type=keyword") - ); - - List requests = new ArrayList<>(); - 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")); - requests.add(client().prepareIndex(indexName, childType, "3").setParent("1").setSource("color", "black", "size", "38")); - 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, 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")); - requests.add(client().prepareIndex(indexName, childType, "9").setParent("2").setSource("color", "black", "size", "38")); - requests.add(client().prepareIndex(indexName, childType, "10").setParent("2").setSource("color", "black", "size", "40")); - requests.add(client().prepareIndex(indexName, childType, "11").setParent("2").setSource("color", "orange", "size", "36")); - requests.add(client().prepareIndex(indexName, childType, "12").setParent("2").setSource("color", "green", "size", "44")); - indexRandom(true, requests); - - SearchResponse response = client().prepareSearch(indexName).setTypes(masterType) - .setQuery(hasChildQuery(childType, termQuery("color", "orange"), ScoreMode.None)) -.addAggregation(children("my-refinements", childType) - .subAggregation(terms("my-colors").field("color")) - .subAggregation(terms("my-sizes").field("size")) - ).get(); - assertNoFailures(response); - assertHitCount(response, 1); - - Children childrenAgg = response.getAggregations().get("my-refinements"); - assertThat(childrenAgg.getDocCount(), equalTo(7L)); - - Terms termsAgg = childrenAgg.getAggregations().get("my-colors"); - assertThat(termsAgg.getBuckets().size(), equalTo(4)); - assertThat(termsAgg.getBucketByKey("black").getDocCount(), equalTo(3L)); - assertThat(termsAgg.getBucketByKey("blue").getDocCount(), equalTo(2L)); - assertThat(termsAgg.getBucketByKey("green").getDocCount(), equalTo(1L)); - assertThat(termsAgg.getBucketByKey("orange").getDocCount(), equalTo(1L)); - - termsAgg = childrenAgg.getAggregations().get("my-sizes"); - assertThat(termsAgg.getBuckets().size(), equalTo(6)); - assertThat(termsAgg.getBucketByKey("36").getDocCount(), equalTo(2L)); - assertThat(termsAgg.getBucketByKey("32").getDocCount(), equalTo(1L)); - assertThat(termsAgg.getBucketByKey("34").getDocCount(), equalTo(1L)); - assertThat(termsAgg.getBucketByKey("38").getDocCount(), equalTo(1L)); - assertThat(termsAgg.getBucketByKey("40").getDocCount(), equalTo(1L)); - assertThat(termsAgg.getBucketByKey("44").getDocCount(), equalTo(1L)); - } - - public void testHierarchicalChildrenAggs() { - String indexName = "geo"; - String grandParentType = "continent"; - String parentType = "country"; - String childType = "city"; - assertAcked( - prepareCreate(indexName) - .setSettings(Settings.builder() - .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) - ) - .setSettings("index.mapping.single_type", false) - .addMapping(grandParentType, "name", "type=keyword") - .addMapping(parentType, "_parent", "type=" + grandParentType) - .addMapping(childType, "_parent", "type=" + parentType) - ); - - client().prepareIndex(indexName, grandParentType, "1").setSource("name", "europe").get(); - client().prepareIndex(indexName, parentType, "2").setParent("1").setSource("name", "belgium").get(); - client().prepareIndex(indexName, childType, "3").setParent("2").setRouting("1").setSource("name", "brussels").get(); - refresh(); - - SearchResponse response = client().prepareSearch(indexName) - .setQuery(matchQuery("name", "europe")) - .addAggregation( - children(parentType, parentType).subAggregation(children(childType, childType).subAggregation( - terms("name").field("name") - ) - ) - ) - .get(); - assertNoFailures(response); - assertHitCount(response, 1); - - Children children = response.getAggregations().get(parentType); - assertThat(children.getName(), equalTo(parentType)); - assertThat(children.getDocCount(), equalTo(1L)); - children = children.getAggregations().get(childType); - assertThat(children.getName(), equalTo(childType)); - assertThat(children.getDocCount(), equalTo(1L)); - Terms terms = children.getAggregations().get("name"); - assertThat(terms.getBuckets().size(), equalTo(1)); - assertThat(terms.getBuckets().get(0).getKey().toString(), equalTo("brussels")); - assertThat(terms.getBuckets().get(0).getDocCount(), equalTo(1L)); - } - - public void testPostCollectAllLeafReaders() throws Exception { - // The 'towns' and 'parent_names' aggs operate on parent docs and if child docs are in different segments we need - // to ensure those segments which child docs are also evaluated to in the post collect phase. - - // Before we only evaluated segments that yielded matches in 'towns' and 'parent_names' aggs, which caused - // us to miss to evaluate child docs in segments we didn't have parent matches for. - - assertAcked( - prepareCreate("index") - .setSettings("index.mapping.single_type", false) - .addMapping("parentType", "name", "type=keyword", "town", "type=keyword") - .addMapping("childType", "_parent", "type=parentType", "name", "type=keyword", "age", "type=integer") - ); - List requests = new ArrayList<>(); - requests.add(client().prepareIndex("index", "parentType", "1").setSource("name", "Bob", "town", "Memphis")); - requests.add(client().prepareIndex("index", "parentType", "2").setSource("name", "Alice", "town", "Chicago")); - requests.add(client().prepareIndex("index", "parentType", "3").setSource("name", "Bill", "town", "Chicago")); - requests.add(client().prepareIndex("index", "childType", "1").setSource("name", "Jill", "age", 5).setParent("1")); - requests.add(client().prepareIndex("index", "childType", "2").setSource("name", "Joey", "age", 3).setParent("1")); - requests.add(client().prepareIndex("index", "childType", "3").setSource("name", "John", "age", 2).setParent("2")); - requests.add(client().prepareIndex("index", "childType", "4").setSource("name", "Betty", "age", 6).setParent("3")); - requests.add(client().prepareIndex("index", "childType", "5").setSource("name", "Dan", "age", 1).setParent("3")); - indexRandom(true, requests); - - SearchResponse response = client().prepareSearch("index") - .setSize(0) - .addAggregation(AggregationBuilders.terms("towns").field("town") - .subAggregation(AggregationBuilders.terms("parent_names").field("name") -.subAggregation(AggregationBuilders.children("child_docs", "childType")) - ) - ) - .get(); - - Terms towns = response.getAggregations().get("towns"); - assertThat(towns.getBuckets().size(), equalTo(2)); - assertThat(towns.getBuckets().get(0).getKeyAsString(), equalTo("Chicago")); - assertThat(towns.getBuckets().get(0).getDocCount(), equalTo(2L)); - - Terms parents = towns.getBuckets().get(0).getAggregations().get("parent_names"); - assertThat(parents.getBuckets().size(), equalTo(2)); - assertThat(parents.getBuckets().get(0).getKeyAsString(), equalTo("Alice")); - assertThat(parents.getBuckets().get(0).getDocCount(), equalTo(1L)); - Children children = parents.getBuckets().get(0).getAggregations().get("child_docs"); - assertThat(children.getDocCount(), equalTo(1L)); - - assertThat(parents.getBuckets().get(1).getKeyAsString(), equalTo("Bill")); - assertThat(parents.getBuckets().get(1).getDocCount(), equalTo(1L)); - children = parents.getBuckets().get(1).getAggregations().get("child_docs"); - assertThat(children.getDocCount(), equalTo(2L)); - - assertThat(towns.getBuckets().get(1).getKeyAsString(), equalTo("Memphis")); - assertThat(towns.getBuckets().get(1).getDocCount(), equalTo(1L)); - parents = towns.getBuckets().get(1).getAggregations().get("parent_names"); - assertThat(parents.getBuckets().size(), equalTo(1)); - assertThat(parents.getBuckets().get(0).getKeyAsString(), equalTo("Bob")); - assertThat(parents.getBuckets().get(0).getDocCount(), equalTo(1L)); - children = parents.getBuckets().get(0).getAggregations().get("child_docs"); - assertThat(children.getDocCount(), equalTo(2L)); - } - - private static final class Control { - - final String category; - final Set articleIds = new HashSet<>(); - final Set commentIds = new HashSet<>(); - final Map> commenterToCommentId = new HashMap<>(); - - private Control(String category) { - this.category = category; - } - } - -} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenTests.java deleted file mode 100644 index 4098e85c62..0000000000 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenTests.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.search.aggregations.bucket; - -import org.elasticsearch.search.aggregations.BaseAggregationTestCase; -import org.elasticsearch.search.aggregations.bucket.children.ChildrenAggregationBuilder; - -public class ChildrenTests extends BaseAggregationTestCase { - - @Override - protected ChildrenAggregationBuilder createTestAggregatorBuilder() { - String name = randomAlphaOfLengthBetween(3, 20); - String childType = randomAlphaOfLengthBetween(5, 40); - ChildrenAggregationBuilder factory = new ChildrenAggregationBuilder(name, childType); - return factory; - } - -} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java deleted file mode 100644 index 8da1f0a90e..0000000000 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.search.aggregations.bucket; - -import org.elasticsearch.search.aggregations.InternalAggregation; -import org.elasticsearch.search.aggregations.InternalAggregations; -import org.elasticsearch.search.aggregations.metrics.max.InternalMax; -import org.elasticsearch.search.aggregations.metrics.min.InternalMin; -import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.elasticsearch.test.InternalAggregationTestCase; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; - -public abstract class InternalSingleBucketAggregationTestCase - extends InternalAggregationTestCase { - private final boolean hasInternalMax = randomBoolean(); - private final boolean hasInternalMin = randomBoolean(); - - protected abstract T createTestInstance(String name, long docCount, InternalAggregations aggregations, - List pipelineAggregators, Map metaData); - protected abstract void extraAssertReduced(T reduced, List inputs); - - @Override - protected final T createTestInstance(String name, List pipelineAggregators, Map metaData) { - List internal = new ArrayList<>(); - if (hasInternalMax) { - internal.add(new InternalMax("max", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap())); - } - if (hasInternalMin) { - internal.add(new InternalMin("min", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap())); - } - // we shouldn't use the full long range here since we sum doc count on reduce, and don't want to overflow the long range there - long docCount = between(0, Integer.MAX_VALUE); - return createTestInstance(name, docCount, new InternalAggregations(internal), pipelineAggregators, metaData); - } - - @Override - protected final void assertReduced(T reduced, List inputs) { - assertEquals(inputs.stream().mapToLong(InternalSingleBucketAggregation::getDocCount).sum(), reduced.getDocCount()); - if (hasInternalMax) { - double expected = inputs.stream().mapToDouble(i -> { - InternalMax max = i.getAggregations().get("max"); - return max.getValue(); - }).max().getAsDouble(); - InternalMax reducedMax = reduced.getAggregations().get("max"); - assertEquals(expected, reducedMax.getValue(), 0); - } - if (hasInternalMin) { - double expected = inputs.stream().mapToDouble(i -> { - InternalMin min = i.getAggregations().get("min"); - return min.getValue(); - }).min().getAsDouble(); - InternalMin reducedMin = reduced.getAggregations().get("min"); - assertEquals(expected, reducedMin.getValue(), 0); - } - extraAssertReduced(reduced, inputs); - } -} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildrenTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildrenTests.java deleted file mode 100644 index b248d5ed98..0000000000 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/InternalChildrenTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.search.aggregations.bucket.children; - -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.pipeline.PipelineAggregator; - -import java.util.List; -import java.util.Map; - -public class InternalChildrenTests extends InternalSingleBucketAggregationTestCase { - @Override - protected InternalChildren createTestInstance(String name, long docCount, InternalAggregations aggregations, - List pipelineAggregators, Map metaData) { - return new InternalChildren(name, docCount, aggregations, pipelineAggregators, metaData); - } - - @Override - protected void extraAssertReduced(InternalChildren reduced, List inputs) { - // Nothing extra to assert - } - - @Override - protected Reader instanceReader() { - return InternalChildren::new; - } - -} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregatorTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregatorTests.java deleted file mode 100644 index 17152bc450..0000000000 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregatorTests.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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.search.aggregations.bucket.children; - -import org.apache.lucene.document.Field; -import org.apache.lucene.document.SortedDocValuesField; -import org.apache.lucene.document.SortedNumericDocValuesField; -import org.apache.lucene.document.StringField; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.RandomIndexWriter; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermInSetQuery; -import org.apache.lucene.store.Directory; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.Version; -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.collect.Tuple; -import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.mapper.ContentPath; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.Mapper; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.NumberFieldMapper; -import org.elasticsearch.index.mapper.ParentFieldMapper; -import org.elasticsearch.index.mapper.TypeFieldMapper; -import org.elasticsearch.index.mapper.Uid; -import org.elasticsearch.index.mapper.UidFieldMapper; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.search.aggregations.AggregatorTestCase; -import org.elasticsearch.search.aggregations.metrics.min.InternalMin; -import org.elasticsearch.search.aggregations.metrics.min.MinAggregationBuilder; -import org.mockito.Mockito; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ParentToChildrenAggregatorTests extends AggregatorTestCase { - - private static final String CHILD_TYPE = "child_type"; - private static final String PARENT_TYPE = "parent_type"; - - public void testNoDocs() throws IOException { - Directory directory = newDirectory(); - - RandomIndexWriter indexWriter = new RandomIndexWriter(random(), directory); - // intentionally not writing any docs - indexWriter.close(); - IndexReader indexReader = DirectoryReader.open(directory); - - testCase(new MatchAllDocsQuery(), newSearcher(indexReader, false, true), parentToChild -> { - assertEquals(0, parentToChild.getDocCount()); - assertEquals(Double.POSITIVE_INFINITY, ((InternalMin) parentToChild.getAggregations().get("in_child")).getValue(), - Double.MIN_VALUE); - }); - indexReader.close(); - directory.close(); - } - - public void testParentChild() throws IOException { - Directory directory = newDirectory(); - RandomIndexWriter indexWriter = new RandomIndexWriter(random(), directory); - - final Map> expectedParentChildRelations = setupIndex(indexWriter); - indexWriter.close(); - - IndexReader indexReader = ElasticsearchDirectoryReader.wrap(DirectoryReader.open(directory), - new ShardId(new Index("foo", "_na_"), 1)); - // TODO set "maybeWrap" to true for IndexSearcher once #23338 is resolved - IndexSearcher indexSearcher = newSearcher(indexReader, false, true); - - testCase(new MatchAllDocsQuery(), indexSearcher, child -> { - int expectedTotalChildren = 0; - int expectedMinValue = Integer.MAX_VALUE; - for (Tuple expectedValues : expectedParentChildRelations.values()) { - expectedTotalChildren += expectedValues.v1(); - expectedMinValue = Math.min(expectedMinValue, expectedValues.v2()); - } - assertEquals(expectedTotalChildren, child.getDocCount()); - assertEquals(expectedMinValue, ((InternalMin) child.getAggregations().get("in_child")).getValue(), Double.MIN_VALUE); - }); - - for (String parent : expectedParentChildRelations.keySet()) { - testCase(new TermInSetQuery(UidFieldMapper.NAME, new BytesRef(Uid.createUid(PARENT_TYPE, parent))), indexSearcher, child -> { - assertEquals((long) expectedParentChildRelations.get(parent).v1(), child.getDocCount()); - assertEquals(expectedParentChildRelations.get(parent).v2(), - ((InternalMin) child.getAggregations().get("in_child")).getValue(), Double.MIN_VALUE); - }); - } - indexReader.close(); - directory.close(); - } - - private static Map> setupIndex(RandomIndexWriter iw) throws IOException { - Map> expectedValues = new HashMap<>(); - int numParents = randomIntBetween(1, 10); - for (int i = 0; i < numParents; i++) { - String parent = "parent" + i; - iw.addDocument(createParentDocument(parent)); - int numChildren = randomIntBetween(1, 10); - int minValue = Integer.MAX_VALUE; - for (int c = 0; c < numChildren; c++) { - int randomValue = randomIntBetween(0, 100); - minValue = Math.min(minValue, randomValue); - iw.addDocument(createChildDocument("child" + c + "_" + parent, parent, randomValue)); - } - expectedValues.put(parent, new Tuple<>(numChildren, minValue)); - } - return expectedValues; - } - - private static List createParentDocument(String id) { - return Arrays.asList(new StringField(TypeFieldMapper.NAME, PARENT_TYPE, Field.Store.NO), - new StringField(UidFieldMapper.NAME, Uid.createUid(PARENT_TYPE, id), Field.Store.NO), - createJoinField(PARENT_TYPE, id)); - } - - private static List createChildDocument(String childId, String parentId, int value) { - return Arrays.asList(new StringField(TypeFieldMapper.NAME, CHILD_TYPE, Field.Store.NO), - new StringField(UidFieldMapper.NAME, Uid.createUid(CHILD_TYPE, childId), Field.Store.NO), - new SortedNumericDocValuesField("number", value), - createJoinField(PARENT_TYPE, parentId)); - } - - private static SortedDocValuesField createJoinField(String parentType, String id) { - return new SortedDocValuesField(ParentFieldMapper.joinField(parentType), new BytesRef(id)); - } - - @Override - protected MapperService mapperServiceMock() { - MapperService mapperService = mock(MapperService.class); - DocumentMapper childDocMapper = mock(DocumentMapper.class); - DocumentMapper parentDocMapper = mock(DocumentMapper.class); - ParentFieldMapper parentFieldMapper = createParentFieldMapper(); - when(childDocMapper.parentFieldMapper()).thenReturn(parentFieldMapper); - when(parentDocMapper.parentFieldMapper()).thenReturn(parentFieldMapper); - when(mapperService.documentMapper(CHILD_TYPE)).thenReturn(childDocMapper); - when(mapperService.documentMapper(PARENT_TYPE)).thenReturn(parentDocMapper); - when(mapperService.docMappers(false)).thenReturn(Arrays.asList(new DocumentMapper[] { childDocMapper, parentDocMapper })); - when(parentDocMapper.typeFilter(Mockito.any())).thenReturn(new TypeFieldMapper.TypesQuery(new BytesRef(PARENT_TYPE))); - when(childDocMapper.typeFilter(Mockito.any())).thenReturn(new TypeFieldMapper.TypesQuery(new BytesRef(CHILD_TYPE))); - return mapperService; - } - - private static ParentFieldMapper createParentFieldMapper() { - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); - return new ParentFieldMapper.Builder("parent").type(PARENT_TYPE).build(new Mapper.BuilderContext(settings, new ContentPath(0))); - } - - private void testCase(Query query, IndexSearcher indexSearcher, Consumer verify) - throws IOException { - - ChildrenAggregationBuilder aggregationBuilder = new ChildrenAggregationBuilder("_name", CHILD_TYPE); - aggregationBuilder.subAggregation(new MinAggregationBuilder("in_child").field("number")); - - MappedFieldType fieldType = new NumberFieldMapper.NumberFieldType(NumberFieldMapper.NumberType.LONG); - fieldType.setName("number"); - InternalChildren result = search(indexSearcher, query, aggregationBuilder, fieldType); - verify.accept(result); - } -} 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 3e74b9c218..464f081f6c 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 @@ 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; 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 9092c3e028..2a284746bf 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 @@ 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; 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 f3e151721b..1a702e9402 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 @@ 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; 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 7b41072366..a330c8a146 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 @@ 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; 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 f918024733..069ac03829 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 @@ 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; 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 1c4fb6d2a6..23facaf8fd 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 @@ 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 instanceReader() { return InternalSampler::new; } -} \ No newline at end of file +} -- cgit v1.2.3