33
33
import org .elasticsearch .common .util .IntArray ;
34
34
import org .elasticsearch .common .util .LongHash ;
35
35
import org .elasticsearch .common .xcontent .XContentBuilder ;
36
- import org .elasticsearch .index .fielddata .AbstractSortedSetDocValues ;
37
36
import org .elasticsearch .search .DocValueFormat ;
38
37
import org .elasticsearch .search .aggregations .Aggregator ;
39
38
import org .elasticsearch .search .aggregations .AggregatorFactories ;
@@ -73,6 +72,8 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
73
72
private final long valueCount ;
74
73
private final GlobalOrdLookupFunction lookupGlobalOrd ;
75
74
protected final CollectionStrategy collectionStrategy ;
75
+ protected int segmentsWithSingleValuedOrds = 0 ;
76
+ protected int segmentsWithMultiValuedOrds = 0 ;
76
77
77
78
public interface GlobalOrdLookupFunction {
78
79
BytesRef apply (long ord ) throws IOException ;
@@ -102,32 +103,68 @@ public GlobalOrdinalsStringTermsAggregator(
102
103
valuesSource .globalOrdinalsValues (context .searcher ().getIndexReader ().leaves ().get (0 )) : DocValues .emptySortedSet ();
103
104
this .valueCount = values .getValueCount ();
104
105
this .lookupGlobalOrd = values ::lookupOrd ;
105
- this .acceptedGlobalOrdinals = includeExclude == null ? l -> true : includeExclude .acceptedGlobalOrdinals (values )::get ;
106
+ this .acceptedGlobalOrdinals = includeExclude == null ? ALWAYS_TRUE : includeExclude .acceptedGlobalOrdinals (values )::get ;
106
107
this .collectionStrategy = remapGlobalOrds ? new RemapGlobalOrds () : new DenseGlobalOrds ();
107
108
}
108
109
109
110
String descriptCollectionStrategy () {
110
111
return collectionStrategy .describe ();
111
112
}
112
113
113
- private SortedSetDocValues getGlobalOrds (LeafReaderContext ctx ) throws IOException {
114
- return acceptedGlobalOrdinals == null ?
115
- valuesSource .globalOrdinalsValues (ctx ) : new FilteredOrdinals (valuesSource .globalOrdinalsValues (ctx ), acceptedGlobalOrdinals );
116
- }
117
-
118
114
@ Override
119
115
public LeafBucketCollector getLeafCollector (LeafReaderContext ctx , LeafBucketCollector sub ) throws IOException {
120
- SortedSetDocValues globalOrds = getGlobalOrds (ctx );
116
+ SortedSetDocValues globalOrds = valuesSource . globalOrdinalsValues (ctx );
121
117
collectionStrategy .globalOrdsReady (globalOrds );
122
118
SortedDocValues singleValues = DocValues .unwrapSingleton (globalOrds );
123
119
if (singleValues != null ) {
120
+ segmentsWithSingleValuedOrds ++;
121
+ if (acceptedGlobalOrdinals == ALWAYS_TRUE ) {
122
+ /*
123
+ * Optimize when there isn't a filter because that is very
124
+ * common and marginally faster.
125
+ */
126
+ return resultStrategy .wrapCollector (new LeafBucketCollectorBase (sub , globalOrds ) {
127
+ @ Override
128
+ public void collect (int doc , long owningBucketOrd ) throws IOException {
129
+ assert owningBucketOrd == 0 ;
130
+ if (false == singleValues .advanceExact (doc )) {
131
+ return ;
132
+ }
133
+ int globalOrd = singleValues .ordValue ();
134
+ collectionStrategy .collectGlobalOrd (doc , globalOrd , sub );
135
+ }
136
+ });
137
+ }
124
138
return resultStrategy .wrapCollector (new LeafBucketCollectorBase (sub , globalOrds ) {
125
139
@ Override
126
140
public void collect (int doc , long owningBucketOrd ) throws IOException {
127
141
assert owningBucketOrd == 0 ;
128
- if (singleValues .advanceExact (doc )) {
129
- int ord = singleValues .ordValue ();
130
- collectionStrategy .collectGlobalOrd (doc , ord , sub );
142
+ if (false == singleValues .advanceExact (doc )) {
143
+ return ;
144
+ }
145
+ int globalOrd = singleValues .ordValue ();
146
+ if (false == acceptedGlobalOrdinals .test (globalOrd )) {
147
+ return ;
148
+ }
149
+ collectionStrategy .collectGlobalOrd (doc , globalOrd , sub );
150
+ }
151
+ });
152
+ }
153
+ segmentsWithMultiValuedOrds ++;
154
+ if (acceptedGlobalOrdinals == ALWAYS_TRUE ) {
155
+ /*
156
+ * Optimize when there isn't a filter because that is very
157
+ * common and marginally faster.
158
+ */
159
+ return resultStrategy .wrapCollector (new LeafBucketCollectorBase (sub , globalOrds ) {
160
+ @ Override
161
+ public void collect (int doc , long owningBucketOrd ) throws IOException {
162
+ assert owningBucketOrd == 0 ;
163
+ if (false == globalOrds .advanceExact (doc )) {
164
+ return ;
165
+ }
166
+ for (long globalOrd = globalOrds .nextOrd (); globalOrd != NO_MORE_ORDS ; globalOrd = globalOrds .nextOrd ()) {
167
+ collectionStrategy .collectGlobalOrd (doc , globalOrd , sub );
131
168
}
132
169
}
133
170
});
@@ -136,10 +173,14 @@ public void collect(int doc, long owningBucketOrd) throws IOException {
136
173
@ Override
137
174
public void collect (int doc , long owningBucketOrd ) throws IOException {
138
175
assert owningBucketOrd == 0 ;
139
- if (globalOrds .advanceExact (doc )) {
140
- for (long globalOrd = globalOrds .nextOrd (); globalOrd != NO_MORE_ORDS ; globalOrd = globalOrds .nextOrd ()) {
141
- collectionStrategy .collectGlobalOrd (doc , globalOrd , sub );
176
+ if (false == globalOrds .advanceExact (doc )) {
177
+ return ;
178
+ }
179
+ for (long globalOrd = globalOrds .nextOrd (); globalOrd != NO_MORE_ORDS ; globalOrd = globalOrds .nextOrd ()) {
180
+ if (false == acceptedGlobalOrdinals .test (globalOrd )) {
181
+ continue ;
142
182
}
183
+ collectionStrategy .collectGlobalOrd (doc , globalOrd , sub );
143
184
}
144
185
}
145
186
});
@@ -160,6 +201,9 @@ public void collectDebugInfo(BiConsumer<String, Object> add) {
160
201
super .collectDebugInfo (add );
161
202
add .accept ("collection_strategy" , collectionStrategy .describe ());
162
203
add .accept ("result_strategy" , resultStrategy .describe ());
204
+ add .accept ("segments_with_single_valued_ords" , segmentsWithSingleValuedOrds );
205
+ add .accept ("segments_with_multi_valued_ords" , segmentsWithMultiValuedOrds );
206
+ add .accept ("has_filter" , acceptedGlobalOrdinals != ALWAYS_TRUE );
163
207
}
164
208
165
209
/**
@@ -253,26 +297,31 @@ public LeafBucketCollector getLeafCollector(LeafReaderContext ctx, LeafBucketCol
253
297
assert sub == LeafBucketCollector .NO_OP_COLLECTOR ;
254
298
final SortedDocValues singleValues = DocValues .unwrapSingleton (segmentOrds );
255
299
mapping = valuesSource .globalOrdinalsMapping (ctx );
300
+ // Dense mode doesn't support include/exclude so we don't have to check it here.
256
301
if (singleValues != null ) {
302
+ segmentsWithSingleValuedOrds ++;
257
303
return resultStrategy .wrapCollector (new LeafBucketCollectorBase (sub , segmentOrds ) {
258
304
@ Override
259
305
public void collect (int doc , long owningBucketOrd ) throws IOException {
260
306
assert owningBucketOrd == 0 ;
261
- if (singleValues .advanceExact (doc )) {
262
- final int ord = singleValues .ordValue ();
263
- segmentDocCounts .increment (ord + 1 , 1 );
307
+ if (false == singleValues .advanceExact (doc )) {
308
+ return ;
264
309
}
310
+ int ord = singleValues .ordValue ();
311
+ segmentDocCounts .increment (ord + 1 , 1 );
265
312
}
266
313
});
267
314
}
315
+ segmentsWithMultiValuedOrds ++;
268
316
return resultStrategy .wrapCollector (new LeafBucketCollectorBase (sub , segmentOrds ) {
269
317
@ Override
270
318
public void collect (int doc , long owningBucketOrd ) throws IOException {
271
319
assert owningBucketOrd == 0 ;
272
- if (segmentOrds .advanceExact (doc )) {
273
- for (long segmentOrd = segmentOrds .nextOrd (); segmentOrd != NO_MORE_ORDS ; segmentOrd = segmentOrds .nextOrd ()) {
274
- segmentDocCounts .increment (segmentOrd + 1 , 1 );
275
- }
320
+ if (false == segmentOrds .advanceExact (doc )) {
321
+ return ;
322
+ }
323
+ for (long segmentOrd = segmentOrds .nextOrd (); segmentOrd != NO_MORE_ORDS ; segmentOrd = segmentOrds .nextOrd ()) {
324
+ segmentDocCounts .increment (segmentOrd + 1 , 1 );
276
325
}
277
326
}
278
327
});
@@ -306,52 +355,6 @@ private void mapSegmentCountsToGlobalCounts(LongUnaryOperator mapping) throws IO
306
355
}
307
356
}
308
357
309
- private static final class FilteredOrdinals extends AbstractSortedSetDocValues {
310
-
311
- private final SortedSetDocValues inner ;
312
- private final LongPredicate accepted ;
313
-
314
- private FilteredOrdinals (SortedSetDocValues inner , LongPredicate accepted ) {
315
- this .inner = inner ;
316
- this .accepted = accepted ;
317
- }
318
-
319
- @ Override
320
- public long getValueCount () {
321
- return inner .getValueCount ();
322
- }
323
-
324
- @ Override
325
- public BytesRef lookupOrd (long ord ) throws IOException {
326
- return inner .lookupOrd (ord );
327
- }
328
-
329
- @ Override
330
- public long nextOrd () throws IOException {
331
- for (long ord = inner .nextOrd (); ord != NO_MORE_ORDS ; ord = inner .nextOrd ()) {
332
- if (accepted .test (ord )) {
333
- return ord ;
334
- }
335
- }
336
- return NO_MORE_ORDS ;
337
- }
338
-
339
- @ Override
340
- public boolean advanceExact (int target ) throws IOException {
341
- if (inner .advanceExact (target )) {
342
- for (long ord = inner .nextOrd (); ord != NO_MORE_ORDS ; ord = inner .nextOrd ()) {
343
- if (accepted .test (ord )) {
344
- // reset the iterator
345
- boolean advanced = inner .advanceExact (target );
346
- assert advanced ;
347
- return true ;
348
- }
349
- }
350
- }
351
- return false ;
352
- }
353
- }
354
-
355
358
/**
356
359
* Strategy for collecting global ordinals.
357
360
* <p>
@@ -800,4 +803,9 @@ private void oversizedCopy(BytesRef from, BytesRef to) {
800
803
System .arraycopy (from .bytes , from .offset , to .bytes , 0 , from .length );
801
804
}
802
805
}
806
+
807
+ /**
808
+ * Predicate used for {@link #acceptedGlobalOrdinals} if there is no filter.
809
+ */
810
+ private static final LongPredicate ALWAYS_TRUE = l -> true ;
803
811
}
0 commit comments