|
@@ -33,7 +33,6 @@ import org.elasticsearch.common.lease.Releasables;
|
|
|
import org.elasticsearch.common.util.IntArray;
|
|
|
import org.elasticsearch.common.util.LongHash;
|
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
-import org.elasticsearch.index.fielddata.AbstractSortedSetDocValues;
|
|
|
import org.elasticsearch.search.DocValueFormat;
|
|
|
import org.elasticsearch.search.aggregations.Aggregator;
|
|
|
import org.elasticsearch.search.aggregations.AggregatorFactories;
|
|
@@ -73,6 +72,8 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
private final long valueCount;
|
|
|
private final GlobalOrdLookupFunction lookupGlobalOrd;
|
|
|
protected final CollectionStrategy collectionStrategy;
|
|
|
+ protected int segmentsWithSingleValuedOrds = 0;
|
|
|
+ protected int segmentsWithMultiValuedOrds = 0;
|
|
|
|
|
|
public interface GlobalOrdLookupFunction {
|
|
|
BytesRef apply(long ord) throws IOException;
|
|
@@ -102,7 +103,7 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
valuesSource.globalOrdinalsValues(context.searcher().getIndexReader().leaves().get(0)) : DocValues.emptySortedSet();
|
|
|
this.valueCount = values.getValueCount();
|
|
|
this.lookupGlobalOrd = values::lookupOrd;
|
|
|
- this.acceptedGlobalOrdinals = includeExclude == null ? l -> true : includeExclude.acceptedGlobalOrdinals(values)::get;
|
|
|
+ this.acceptedGlobalOrdinals = includeExclude == null ? ALWAYS_TRUE : includeExclude.acceptedGlobalOrdinals(values)::get;
|
|
|
this.collectionStrategy = remapGlobalOrds ? new RemapGlobalOrds() : new DenseGlobalOrds();
|
|
|
}
|
|
|
|
|
@@ -110,24 +111,60 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
return collectionStrategy.describe();
|
|
|
}
|
|
|
|
|
|
- private SortedSetDocValues getGlobalOrds(LeafReaderContext ctx) throws IOException {
|
|
|
- return acceptedGlobalOrdinals == null ?
|
|
|
- valuesSource.globalOrdinalsValues(ctx) : new FilteredOrdinals(valuesSource.globalOrdinalsValues(ctx), acceptedGlobalOrdinals);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public LeafBucketCollector getLeafCollector(LeafReaderContext ctx, LeafBucketCollector sub) throws IOException {
|
|
|
- SortedSetDocValues globalOrds = getGlobalOrds(ctx);
|
|
|
+ SortedSetDocValues globalOrds = valuesSource.globalOrdinalsValues(ctx);
|
|
|
collectionStrategy.globalOrdsReady(globalOrds);
|
|
|
SortedDocValues singleValues = DocValues.unwrapSingleton(globalOrds);
|
|
|
if (singleValues != null) {
|
|
|
+ segmentsWithSingleValuedOrds++;
|
|
|
+ if (acceptedGlobalOrdinals == ALWAYS_TRUE) {
|
|
|
+ /*
|
|
|
+ * Optimize when there isn't a filter because that is very
|
|
|
+ * common and marginally faster.
|
|
|
+ */
|
|
|
+ return resultStrategy.wrapCollector(new LeafBucketCollectorBase(sub, globalOrds) {
|
|
|
+ @Override
|
|
|
+ public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
+ assert owningBucketOrd == 0;
|
|
|
+ if (false == singleValues.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int globalOrd = singleValues.ordValue();
|
|
|
+ collectionStrategy.collectGlobalOrd(doc, globalOrd, sub);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
return resultStrategy.wrapCollector(new LeafBucketCollectorBase(sub, globalOrds) {
|
|
|
@Override
|
|
|
public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
assert owningBucketOrd == 0;
|
|
|
- if (singleValues.advanceExact(doc)) {
|
|
|
- int ord = singleValues.ordValue();
|
|
|
- collectionStrategy.collectGlobalOrd(doc, ord, sub);
|
|
|
+ if (false == singleValues.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int globalOrd = singleValues.ordValue();
|
|
|
+ if (false == acceptedGlobalOrdinals.test(globalOrd)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ collectionStrategy.collectGlobalOrd(doc, globalOrd, sub);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ segmentsWithMultiValuedOrds++;
|
|
|
+ if (acceptedGlobalOrdinals == ALWAYS_TRUE) {
|
|
|
+ /*
|
|
|
+ * Optimize when there isn't a filter because that is very
|
|
|
+ * common and marginally faster.
|
|
|
+ */
|
|
|
+ return resultStrategy.wrapCollector(new LeafBucketCollectorBase(sub, globalOrds) {
|
|
|
+ @Override
|
|
|
+ public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
+ assert owningBucketOrd == 0;
|
|
|
+ if (false == globalOrds.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (long globalOrd = globalOrds.nextOrd(); globalOrd != NO_MORE_ORDS; globalOrd = globalOrds.nextOrd()) {
|
|
|
+ collectionStrategy.collectGlobalOrd(doc, globalOrd, sub);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -136,10 +173,14 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
@Override
|
|
|
public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
assert owningBucketOrd == 0;
|
|
|
- if (globalOrds.advanceExact(doc)) {
|
|
|
- for (long globalOrd = globalOrds.nextOrd(); globalOrd != NO_MORE_ORDS; globalOrd = globalOrds.nextOrd()) {
|
|
|
- collectionStrategy.collectGlobalOrd(doc, globalOrd, sub);
|
|
|
+ if (false == globalOrds.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (long globalOrd = globalOrds.nextOrd(); globalOrd != NO_MORE_ORDS; globalOrd = globalOrds.nextOrd()) {
|
|
|
+ if (false == acceptedGlobalOrdinals.test(globalOrd)) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ collectionStrategy.collectGlobalOrd(doc, globalOrd, sub);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -160,6 +201,9 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
super.collectDebugInfo(add);
|
|
|
add.accept("collection_strategy", collectionStrategy.describe());
|
|
|
add.accept("result_strategy", resultStrategy.describe());
|
|
|
+ add.accept("segments_with_single_valued_ords", segmentsWithSingleValuedOrds);
|
|
|
+ add.accept("segments_with_multi_valued_ords", segmentsWithMultiValuedOrds);
|
|
|
+ add.accept("has_filter", acceptedGlobalOrdinals != ALWAYS_TRUE);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -253,26 +297,31 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
assert sub == LeafBucketCollector.NO_OP_COLLECTOR;
|
|
|
final SortedDocValues singleValues = DocValues.unwrapSingleton(segmentOrds);
|
|
|
mapping = valuesSource.globalOrdinalsMapping(ctx);
|
|
|
+ // Dense mode doesn't support include/exclude so we don't have to check it here.
|
|
|
if (singleValues != null) {
|
|
|
+ segmentsWithSingleValuedOrds++;
|
|
|
return resultStrategy.wrapCollector(new LeafBucketCollectorBase(sub, segmentOrds) {
|
|
|
@Override
|
|
|
public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
assert owningBucketOrd == 0;
|
|
|
- if (singleValues.advanceExact(doc)) {
|
|
|
- final int ord = singleValues.ordValue();
|
|
|
- segmentDocCounts.increment(ord + 1, 1);
|
|
|
+ if (false == singleValues.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
}
|
|
|
+ int ord = singleValues.ordValue();
|
|
|
+ segmentDocCounts.increment(ord + 1, 1);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+ segmentsWithMultiValuedOrds++;
|
|
|
return resultStrategy.wrapCollector(new LeafBucketCollectorBase(sub, segmentOrds) {
|
|
|
@Override
|
|
|
public void collect(int doc, long owningBucketOrd) throws IOException {
|
|
|
assert owningBucketOrd == 0;
|
|
|
- if (segmentOrds.advanceExact(doc)) {
|
|
|
- for (long segmentOrd = segmentOrds.nextOrd(); segmentOrd != NO_MORE_ORDS; segmentOrd = segmentOrds.nextOrd()) {
|
|
|
- segmentDocCounts.increment(segmentOrd + 1, 1);
|
|
|
- }
|
|
|
+ if (false == segmentOrds.advanceExact(doc)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (long segmentOrd = segmentOrds.nextOrd(); segmentOrd != NO_MORE_ORDS; segmentOrd = segmentOrds.nextOrd()) {
|
|
|
+ segmentDocCounts.increment(segmentOrd + 1, 1);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -306,52 +355,6 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static final class FilteredOrdinals extends AbstractSortedSetDocValues {
|
|
|
-
|
|
|
- private final SortedSetDocValues inner;
|
|
|
- private final LongPredicate accepted;
|
|
|
-
|
|
|
- private FilteredOrdinals(SortedSetDocValues inner, LongPredicate accepted) {
|
|
|
- this.inner = inner;
|
|
|
- this.accepted = accepted;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public long getValueCount() {
|
|
|
- return inner.getValueCount();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public BytesRef lookupOrd(long ord) throws IOException {
|
|
|
- return inner.lookupOrd(ord);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public long nextOrd() throws IOException {
|
|
|
- for (long ord = inner.nextOrd(); ord != NO_MORE_ORDS; ord = inner.nextOrd()) {
|
|
|
- if (accepted.test(ord)) {
|
|
|
- return ord;
|
|
|
- }
|
|
|
- }
|
|
|
- return NO_MORE_ORDS;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean advanceExact(int target) throws IOException {
|
|
|
- if (inner.advanceExact(target)) {
|
|
|
- for (long ord = inner.nextOrd(); ord != NO_MORE_ORDS; ord = inner.nextOrd()) {
|
|
|
- if (accepted.test(ord)) {
|
|
|
- // reset the iterator
|
|
|
- boolean advanced = inner.advanceExact(target);
|
|
|
- assert advanced;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Strategy for collecting global ordinals.
|
|
|
* <p>
|
|
@@ -800,4 +803,9 @@ public class GlobalOrdinalsStringTermsAggregator extends AbstractStringTermsAggr
|
|
|
System.arraycopy(from.bytes, from.offset, to.bytes, 0, from.length);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Predicate used for {@link #acceptedGlobalOrdinals} if there is no filter.
|
|
|
+ */
|
|
|
+ private static final LongPredicate ALWAYS_TRUE = l -> true;
|
|
|
}
|