3434import org .apache .lucene .util .BytesRef ;
3535import org .elasticsearch .Version ;
3636import org .elasticsearch .cluster .metadata .IndexMetaData ;
37- import org .elasticsearch .common .CheckedConsumer ;
37+ import org .elasticsearch .common .collect .Tuple ;
38+ import org .elasticsearch .common .lucene .index .ElasticsearchDirectoryReader ;
3839import org .elasticsearch .common .settings .Settings ;
40+ import org .elasticsearch .index .Index ;
3941import org .elasticsearch .index .mapper .ContentPath ;
4042import org .elasticsearch .index .mapper .DocumentMapper ;
4143import org .elasticsearch .index .mapper .MappedFieldType ;
4648import org .elasticsearch .index .mapper .TypeFieldMapper ;
4749import org .elasticsearch .index .mapper .Uid ;
4850import org .elasticsearch .index .mapper .UidFieldMapper ;
51+ import org .elasticsearch .index .shard .ShardId ;
4952import org .elasticsearch .search .aggregations .AggregatorTestCase ;
5053import org .elasticsearch .search .aggregations .metrics .min .InternalMin ;
5154import org .elasticsearch .search .aggregations .metrics .min .MinAggregationBuilder ;
5255
5356import java .io .IOException ;
5457import java .util .Arrays ;
58+ import java .util .HashMap ;
5559import java .util .List ;
60+ import java .util .Map ;
5661import java .util .function .Consumer ;
5762
5863import static org .mockito .Mockito .mock ;
@@ -64,42 +69,75 @@ public class ParentToChildrenAggregatorTests extends AggregatorTestCase {
6469 private static final String PARENT_TYPE = "parent_type" ;
6570
6671 public void testNoDocs () throws IOException {
67- testCase (new MatchAllDocsQuery (), iw -> {
68- // Intentionally not writing any docs
69- }, parentToChild -> {
72+ Directory directory = newDirectory ();
73+
74+ RandomIndexWriter indexWriter = new RandomIndexWriter (random (), directory );
75+ // intentionally not writing any docs
76+ indexWriter .close ();
77+ IndexReader indexReader = DirectoryReader .open (directory );
78+
79+ testCase (new MatchAllDocsQuery (), newSearcher (indexReader , false , true ), parentToChild -> {
7080 assertEquals (0 , parentToChild .getDocCount ());
7181 assertEquals (Double .POSITIVE_INFINITY , ((InternalMin ) parentToChild .getAggregations ().get ("in_child" )).getValue (),
7282 Double .MIN_VALUE );
7383 });
84+ indexReader .close ();
85+ directory .close ();
7486 }
7587
7688 public void testParentChild () throws IOException {
77- testCase (new MatchAllDocsQuery (), ParentToChildrenAggregatorTests ::setupIndex , child -> {
78- assertEquals (4 , child .getDocCount ());
79- assertEquals (2 , ((InternalMin ) child .getAggregations ().get ("in_child" )).getValue (), Double .MIN_VALUE );
89+ Directory directory = newDirectory ();
90+ RandomIndexWriter indexWriter = new RandomIndexWriter (random (), directory );
91+
92+ final Map <String , Tuple <Integer , Integer >> expectedParentChildRelations = setupIndex (indexWriter );
93+ indexWriter .close ();
94+
95+ IndexReader indexReader = ElasticsearchDirectoryReader .wrap (DirectoryReader .open (directory ),
96+ new ShardId (new Index ("foo" , "_na_" ), 1 ));
97+ // TODO no "maybeWrap" for the searcher because this randomly led to java.lang.ClassCastException:
98+ // org.apache.lucene.search.QueryUtils$FCInvisibleMultiReader cannot be
99+ // cast to org.apache.lucene.index.DirectoryReader
100+ // according to @mvg this can be fixed later but requires bigger changes
101+ IndexSearcher indexSearcher = newSearcher (indexReader , false , true );
102+
103+ testCase (new MatchAllDocsQuery (), indexSearcher , child -> {
104+ int expectedTotalChildren = 0 ;
105+ int expectedMinValue = Integer .MAX_VALUE ;
106+ for (Tuple <Integer , Integer > expectedValues : expectedParentChildRelations .values ()) {
107+ expectedTotalChildren += expectedValues .v1 ();
108+ expectedMinValue = Math .min (expectedMinValue , expectedValues .v2 ());
109+ }
110+ assertEquals (expectedTotalChildren , child .getDocCount ());
111+ assertEquals (expectedMinValue , ((InternalMin ) child .getAggregations ().get ("in_child" )).getValue (), Double .MIN_VALUE );
80112 });
81113
82- testCase (new TermInSetQuery (UidFieldMapper .NAME , new BytesRef (Uid .createUid (PARENT_TYPE , "parent1" ))),
83- ParentToChildrenAggregatorTests ::setupIndex , child -> {
84- assertEquals (1 , child .getDocCount ());
85- assertEquals (10 , ((InternalMin ) child .getAggregations ().get ("in_child" )).getValue (), Double .MIN_VALUE );
86- });
87-
88- testCase (new TermInSetQuery (UidFieldMapper .NAME , new BytesRef (Uid .createUid (PARENT_TYPE , "parent2" ))),
89- ParentToChildrenAggregatorTests ::setupIndex , child -> {
90- assertEquals (3 , child .getDocCount ());
91- assertEquals (2 , ((InternalMin ) child .getAggregations ().get ("in_child" )).getValue (), Double .MIN_VALUE );
92- });
114+ for (String parent : expectedParentChildRelations .keySet ()) {
115+ testCase (new TermInSetQuery (UidFieldMapper .NAME , new BytesRef (Uid .createUid (PARENT_TYPE , parent ))), indexSearcher , child -> {
116+ assertEquals ((long ) expectedParentChildRelations .get (parent ).v1 (), child .getDocCount ());
117+ assertEquals (expectedParentChildRelations .get (parent ).v2 (),
118+ ((InternalMin ) child .getAggregations ().get ("in_child" )).getValue (), Double .MIN_VALUE );
119+ });
120+ }
121+ indexReader .close ();
122+ directory .close ();
93123 }
94124
95- private static void setupIndex (RandomIndexWriter iw ) throws IOException {
96- iw .addDocument (createParentDocument ("parent1" ));
97- iw .addDocument (createChildDocument ("child1" , "parent1" , 10 ));
98-
99- iw .addDocument (createParentDocument ("parent2" ));
100- iw .addDocument (createChildDocument ("child2" , "parent2" , 5 ));
101- iw .addDocument (createChildDocument ("child3" , "parent2" , 2 ));
102- iw .addDocument (createChildDocument ("child4" , "parent2" , 7 ));
125+ private static Map <String , Tuple <Integer , Integer >> setupIndex (RandomIndexWriter iw ) throws IOException {
126+ Map <String , Tuple <Integer , Integer >> expectedValues = new HashMap <>();
127+ int numParents = randomIntBetween (1 , 10 );
128+ for (int i = 0 ; i < numParents ; i ++) {
129+ String parent = "parent" + i ;
130+ iw .addDocument (createParentDocument (parent ));
131+ int numChildren = randomIntBetween (1 , 10 );
132+ int minValue = Integer .MAX_VALUE ;
133+ for (int c = 0 ; c < numChildren ; c ++) {
134+ int randomValue = randomIntBetween (0 , 100 );
135+ minValue = Math .min (minValue , randomValue );
136+ iw .addDocument (createChildDocument ("child" + c + "_" + parent , parent , randomValue ));
137+ }
138+ expectedValues .put (parent , new Tuple <>(numChildren , minValue ));
139+ }
140+ return expectedValues ;
103141 }
104142
105143 private static List <Field > createParentDocument (String id ) {
@@ -140,19 +178,8 @@ private static ParentFieldMapper createParentFieldMapper() {
140178 return new ParentFieldMapper .Builder ("parent" ).type (PARENT_TYPE ).build (new Mapper .BuilderContext (settings , new ContentPath (0 )));
141179 }
142180
143- private void testCase (Query query , CheckedConsumer < RandomIndexWriter , IOException > buildIndex , Consumer <InternalChildren > verify )
181+ private void testCase (Query query , IndexSearcher indexSearcher , Consumer <InternalChildren > verify )
144182 throws IOException {
145- Directory directory = newDirectory ();
146- RandomIndexWriter indexWriter = new RandomIndexWriter (random (), directory );
147- buildIndex .accept (indexWriter );
148- indexWriter .close ();
149-
150- IndexReader indexReader = DirectoryReader .open (directory );
151- // TODO no "maybeWrap" for the searcher because this randomly led to java.lang.ClassCastException:
152- // org.apache.lucene.search.QueryUtils$FCInvisibleMultiReader cannot be
153- // cast to org.apache.lucene.index.DirectoryReader
154- // according to @mvg this can be fixed later but requires bigger changes
155- IndexSearcher indexSearcher = newSearcher (indexReader , false , true );
156183
157184 ChildrenAggregationBuilder aggregationBuilder = new ChildrenAggregationBuilder ("_name" , CHILD_TYPE );
158185 aggregationBuilder .subAggregation (new MinAggregationBuilder ("in_child" ).field ("number" ));
@@ -161,7 +188,5 @@ private void testCase(Query query, CheckedConsumer<RandomIndexWriter, IOExceptio
161188 fieldType .setName ("number" );
162189 InternalChildren result = search (indexSearcher , query , aggregationBuilder , fieldType );
163190 verify .accept (result );
164- indexReader .close ();
165- directory .close ();
166191 }
167192}
0 commit comments