mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-25 14:26:27 +00:00
Upgrade to Lucene r1657571.
Closes #9587 Squashed commit of the following: commit 23ac91dca4b949638ca1d3842fd6db2e00ee1d36 Author: Adrien Grand <jpountz@gmail.com> Date: Thu Feb 5 18:42:28 2015 +0100 Do not compute scores if aggregations do not need it (like top_hits) or use a script (which might compute scores). commit 51262fe2681c067337ca41ab88096ef80a2e8ebb Author: Adrien Grand <jpountz@gmail.com> Date: Thu Feb 5 15:58:38 2015 +0100 Fix more compile errors. commit a074895d55b8b3c898d23f7f5334e564d5271a56 Author: Robert Muir <rmuir@apache.org> Date: Thu Feb 5 09:31:22 2015 -0500 fix a few more obvious ones commit 399c41186cb3c9be70107f6c25b51fc4844f8fde Author: Robert Muir <rmuir@apache.org> Date: Thu Feb 5 09:28:32 2015 -0500 fix some collectors and queries commit 5f46c2f846c5020d5749233b71cbe66ae534ba51 Author: Robert Muir <rmuir@apache.org> Date: Thu Feb 5 09:24:24 2015 -0500 upgrade to lucene r1657571
This commit is contained in:
parent
487ef80c35
commit
9c9b5c27d3
4
pom.xml
4
pom.xml
@ -32,7 +32,7 @@
|
||||
|
||||
<properties>
|
||||
<lucene.version>5.1.0</lucene.version>
|
||||
<lucene.maven.version>5.1.0-snapshot-1656366</lucene.maven.version>
|
||||
<lucene.maven.version>5.1.0-snapshot-1657571</lucene.maven.version>
|
||||
<tests.jvms>auto</tests.jvms>
|
||||
<tests.shuffle>true</tests.shuffle>
|
||||
<tests.output>onerror</tests.output>
|
||||
@ -54,7 +54,7 @@
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Lucene snapshots</id>
|
||||
<url>https://download.elasticsearch.org/lucenesnapshots/1656366</url>
|
||||
<url>https://download.elasticsearch.org/lucenesnapshots/1657571</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
@ -536,6 +536,11 @@ public class Lucene {
|
||||
public void doSetNextReader(LeafReaderContext atomicReaderContext) throws IOException {
|
||||
leafCollector = delegate.getLeafCollector(atomicReaderContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return delegate.needsScores();
|
||||
}
|
||||
}
|
||||
|
||||
private Lucene() {
|
||||
|
@ -60,4 +60,9 @@ public class MinimumScoreCollector extends SimpleCollector {
|
||||
public void doSetNextReader(LeafReaderContext context) throws IOException {
|
||||
leafCollector = collector.getLeafCollector(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -62,7 +62,7 @@ public class AllTermQuery extends SpanTermQuery {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllTermSpanScorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public AllTermSpanScorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
if (this.stats == null) {
|
||||
return null;
|
||||
}
|
||||
@ -146,7 +146,7 @@ public class AllTermQuery extends SpanTermQuery {
|
||||
|
||||
@Override
|
||||
public Explanation explain(LeafReaderContext context, int doc) throws IOException{
|
||||
AllTermSpanScorer scorer = scorer(context, context.reader().getLiveDocs());
|
||||
AllTermSpanScorer scorer = scorer(context, context.reader().getLiveDocs(), true);
|
||||
if (scorer != null) {
|
||||
int newDoc = scorer.advance(doc);
|
||||
if (newDoc == doc) {
|
||||
|
@ -97,4 +97,8 @@ public class FilteredCollector implements XCollector {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return collector.needsScores();
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ public final class MatchNoDocsQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -43,4 +43,9 @@ public class NoopCollector extends SimpleCollector {
|
||||
@Override
|
||||
protected void doSetNextReader(LeafReaderContext context) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -152,11 +152,11 @@ public class FiltersFunctionScoreQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
// we ignore scoreDocsInOrder parameter, because we need to score in
|
||||
// order if documents are scored with a script. The
|
||||
// ShardLookup depends on in order scoring.
|
||||
Scorer subQueryScorer = subQueryWeight.scorer(context, acceptDocs);
|
||||
Scorer subQueryScorer = subQueryWeight.scorer(context, acceptDocs, needsScores);
|
||||
if (subQueryScorer == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -120,11 +120,11 @@ public class FunctionScoreQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
// we ignore scoreDocsInOrder parameter, because we need to score in
|
||||
// order if documents are scored with a script. The
|
||||
// ShardLookup depends on in order scoring.
|
||||
Scorer subQueryScorer = subQueryWeight.scorer(context, acceptDocs);
|
||||
Scorer subQueryScorer = subQueryWeight.scorer(context, acceptDocs, needsScores);
|
||||
if (subQueryScorer == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -96,4 +96,9 @@ final class QueriesLoaderCollector extends SimpleCollector {
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -75,14 +75,14 @@ public class FilteredQueryParser implements QueryParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer filteredScorer(LeafReaderContext context, Weight weight, DocIdSet docIdSet) throws IOException {
|
||||
public Scorer filteredScorer(LeafReaderContext context, Weight weight, DocIdSet docIdSet, boolean needsScores) throws IOException {
|
||||
// CHANGE: If threshold is 0, always pass down the accept docs, don't pay the price of calling nextDoc even...
|
||||
final Bits filterAcceptDocs = docIdSet.bits();
|
||||
if (threshold == 0) {
|
||||
if (filterAcceptDocs != null) {
|
||||
return weight.scorer(context, filterAcceptDocs);
|
||||
return weight.scorer(context, filterAcceptDocs, needsScores);
|
||||
} else {
|
||||
return FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY.filteredScorer(context, weight, docIdSet);
|
||||
return FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY.filteredScorer(context, weight, docIdSet, needsScores);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,11 +91,11 @@ public class FilteredQueryParser implements QueryParser {
|
||||
// default value, don't iterate on only apply filter after query if its not a "fast" docIdSet
|
||||
// TODO: is there a way we could avoid creating an iterator here?
|
||||
if (filterAcceptDocs != null && DocIdSets.isBroken(docIdSet.iterator())) {
|
||||
return FilteredQuery.QUERY_FIRST_FILTER_STRATEGY.filteredScorer(context, weight, docIdSet);
|
||||
return FilteredQuery.QUERY_FIRST_FILTER_STRATEGY.filteredScorer(context, weight, docIdSet, needsScores);
|
||||
}
|
||||
}
|
||||
|
||||
return super.filteredScorer(context, weight, docIdSet);
|
||||
return super.filteredScorer(context, weight, docIdSet, needsScores);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,6 +51,7 @@ import java.util.Set;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
// TODO: Remove me and move the logic to ChildrenQuery when needsScore=false
|
||||
public class ChildrenConstantScoreQuery extends Query {
|
||||
|
||||
private final IndexParentChildFieldData parentChildIndexFieldData;
|
||||
@ -221,7 +222,7 @@ public class ChildrenConstantScoreQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
if (remaining == 0) {
|
||||
return null;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ public class ChildrenQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
DocIdSet parentsSet = parentFilter.getDocIdSet(context, acceptDocs);
|
||||
if (DocIdSets.isEmpty(parentsSet) || remaining == 0) {
|
||||
return null;
|
||||
|
@ -73,7 +73,7 @@ public class CustomQueryWrappingFilter extends NoCacheFilter implements Releasab
|
||||
final DocIdSet set = new DocIdSet() {
|
||||
@Override
|
||||
public DocIdSetIterator iterator() throws IOException {
|
||||
return weight.scorer(leaf, null);
|
||||
return weight.scorer(leaf, null, false);
|
||||
}
|
||||
@Override
|
||||
public boolean isCacheable() { return false; }
|
||||
|
@ -187,7 +187,7 @@ public class ParentConstantScoreQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
DocIdSet childrenDocIdSet = childrenFilter.getDocIdSet(context, acceptDocs);
|
||||
if (DocIdSets.isEmpty(childrenDocIdSet)) {
|
||||
return null;
|
||||
|
@ -251,7 +251,7 @@ public class ParentQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
DocIdSet childrenDocSet = childrenFilter.getDocIdSet(context, acceptDocs);
|
||||
if (DocIdSets.isEmpty(childrenDocSet)) {
|
||||
return null;
|
||||
|
@ -323,8 +323,11 @@ public class TopChildrenQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
ParentDoc[] readerParentDocs = parentDocs.get(context.reader().getCoreCacheKey());
|
||||
// We ignore the needsScores parameter here because there isn't really anything that we
|
||||
// can improve by ignoring scores. Actually this query does not really make sense
|
||||
// with needsScores=false...
|
||||
if (readerParentDocs != null) {
|
||||
if (scoreType == ScoreType.MIN) {
|
||||
return new ParentScorer(this, readerParentDocs) {
|
||||
|
@ -105,8 +105,8 @@ public class IncludeNestedDocsQuery extends Query {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||
final Scorer parentScorer = parentWeight.scorer(context, acceptDocs);
|
||||
public Scorer scorer(LeafReaderContext context, Bits acceptDocs, boolean needsScores) throws IOException {
|
||||
final Scorer parentScorer = parentWeight.scorer(context, acceptDocs, needsScores);
|
||||
|
||||
// no matches
|
||||
if (parentScorer == null) {
|
||||
|
@ -247,8 +247,9 @@ public class IndicesTTLService extends AbstractLifecycleComponent<IndicesTTLServ
|
||||
public void setScorer(Scorer scorer) {
|
||||
}
|
||||
|
||||
public boolean acceptsDocsOutOfOrder() {
|
||||
return true;
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void collect(int doc) {
|
||||
|
@ -110,6 +110,16 @@ abstract class QueryCollector extends SimpleCollector {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
for (Collector collector : aggregatorCollector) {
|
||||
if (collector.needsScores()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSetNextReader(LeafReaderContext context) throws IOException {
|
||||
// we use the UID because id might not be indexed
|
||||
|
@ -94,7 +94,7 @@ public class AggregationPhase implements SearchPhase {
|
||||
}
|
||||
context.aggregations().aggregators(aggregators);
|
||||
if (!collectors.isEmpty()) {
|
||||
context.searcher().addMainQueryCollector(new AggregationsCollector(collectors, aggregationContext));
|
||||
context.searcher().queryCollectors().put(AggregationPhase.class, new AggregationsCollector(collectors, aggregationContext));
|
||||
}
|
||||
aggregationContext.setNextReader(context.searcher().getIndexReader().getContext());
|
||||
}
|
||||
@ -148,6 +148,7 @@ public class AggregationPhase implements SearchPhase {
|
||||
|
||||
// disable aggregations so that they don't run on next pages in case of scrolling
|
||||
context.aggregations(null);
|
||||
context.searcher().queryCollectors().remove(AggregationPhase.class);
|
||||
}
|
||||
|
||||
|
||||
@ -166,6 +167,11 @@ public class AggregationPhase implements SearchPhase {
|
||||
aggregationContext.setScorer(scorer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return aggregationContext.needsScores();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
for (Aggregator collector : collectors) {
|
||||
|
@ -99,6 +99,15 @@ public class AggregatorFactories {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needsScores() {
|
||||
for (AggregatorFactory factory : factories) {
|
||||
if (factory.needsScores()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final static class Empty extends AggregatorFactories {
|
||||
|
||||
private static final AggregatorFactory[] EMPTY_FACTORIES = new AggregatorFactory[0];
|
||||
|
@ -101,6 +101,10 @@ public abstract class AggregatorFactory {
|
||||
this.metaData = metaData;
|
||||
}
|
||||
|
||||
public boolean needsScores() {
|
||||
return factories.needsScores();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method. Given an {@link AggregatorFactory} that creates {@link Aggregator}s that only know how
|
||||
* to collect bucket <tt>0</tt>, this returns an aggregator that can collect any bucket.
|
||||
|
@ -176,5 +176,15 @@ public class TopHitsAggregator extends MetricsAggregator implements ScorerAware
|
||||
throw new AggregationInitializationException("Aggregator [" + name + "] of type [" + type + "] cannot accept sub-aggregations");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
Sort sort = subSearchContext.sort();
|
||||
if (sort != null) {
|
||||
return sort.needsScores() || subSearchContext.trackScores();
|
||||
} else {
|
||||
// sort by score
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,13 @@ public class AggregationContext implements ReaderContextAware, ScorerAware {
|
||||
this.searchContext = searchContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether aggregators which are attached to this context need scores.
|
||||
*/
|
||||
public boolean needsScores() {
|
||||
return searchContext.aggregations().factories().needsScores();
|
||||
}
|
||||
|
||||
public SearchContext searchContext() {
|
||||
return searchContext;
|
||||
}
|
||||
|
@ -64,6 +64,15 @@ public abstract class ValuesSourceAggregatorFactory<VS extends ValuesSource> ext
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
// TODO: we have no way to know whether scripts use the score so
|
||||
// for now we assume that they do but in the future it would be
|
||||
// nice to be able to know if they need scores so that the query
|
||||
// would only provuce scores if required.
|
||||
return config.script != null || super.needsScores();
|
||||
}
|
||||
|
||||
protected abstract Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map<String, Object> metaData) throws IOException;
|
||||
|
||||
protected abstract Aggregator doCreateInternal(VS valuesSource, AggregationContext aggregationContext, Aggregator parent, boolean collectsFromSingleBucket, Map<String, Object> metaData) throws IOException;
|
||||
|
@ -39,7 +39,9 @@ import org.elasticsearch.search.internal.SearchContext.Lifetime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Context-aware extension of {@link IndexSearcher}.
|
||||
@ -60,7 +62,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||
|
||||
private CachedDfSource dfSource;
|
||||
|
||||
private List<Collector> queryCollectors;
|
||||
private Map<Class<?>, Collector> queryCollectors;
|
||||
|
||||
private Stage currentState = Stage.NA;
|
||||
|
||||
@ -84,11 +86,11 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||
* {@link org.elasticsearch.common.lucene.search.XCollector} allowing for a callback
|
||||
* when collection is done.
|
||||
*/
|
||||
public void addMainQueryCollector(Collector collector) {
|
||||
public Map<Class<?>, Collector> queryCollectors() {
|
||||
if (queryCollectors == null) {
|
||||
queryCollectors = new ArrayList<>();
|
||||
queryCollectors = new HashMap<>();
|
||||
}
|
||||
queryCollectors.add(collector);
|
||||
return queryCollectors;
|
||||
}
|
||||
|
||||
public void inStage(Stage stage) {
|
||||
@ -151,7 +153,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||
collector = new FilteredCollector(collector, searchContext.parsedPostFilter().filter());
|
||||
}
|
||||
if (queryCollectors != null && !queryCollectors.isEmpty()) {
|
||||
ArrayList<Collector> allCollectors = new ArrayList<>(queryCollectors);
|
||||
ArrayList<Collector> allCollectors = new ArrayList<>(queryCollectors.values());
|
||||
allCollectors.add(collector);
|
||||
collector = MultiCollector.wrap(allCollectors);
|
||||
}
|
||||
@ -183,7 +185,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||
|
||||
if (currentState == Stage.MAIN_QUERY) {
|
||||
if (queryCollectors != null && !queryCollectors.isEmpty()) {
|
||||
for (Collector queryCollector : queryCollectors) {
|
||||
for (Collector queryCollector : queryCollectors.values()) {
|
||||
if (queryCollector instanceof XCollector) {
|
||||
((XCollector) queryCollector).postCollection();
|
||||
}
|
||||
|
@ -100,6 +100,11 @@ public class ScanContext {
|
||||
return new TopDocs(docs.size(), docs.toArray(new ScoreDoc[docs.size()]), 0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsScores() {
|
||||
return trackScores;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
this.scorer = scorer;
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.index.IndexService;
|
||||
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AggregationCollectorTests extends ElasticsearchSingleNodeTest {
|
||||
|
||||
public void testNeedsScores() throws Exception {
|
||||
IndexService index = createIndex("idx");
|
||||
client().prepareIndex("idx", "type", "1").setSource("f", 5).execute().get();
|
||||
client().admin().indices().prepareRefresh("idx").get();
|
||||
|
||||
// simple field aggregation, no scores needed
|
||||
String fieldAgg = "{ \"my_terms\": {\"terms\": {\"field\": \"f\"}}}";
|
||||
assertFalse(needsScores(index, fieldAgg));
|
||||
|
||||
// agg on a script => scores are needed
|
||||
String scriptAgg = "{ \"my_terms\": {\"terms\": {\"script\": \"doc['f'].value\"}}}";
|
||||
assertTrue(needsScores(index, scriptAgg));
|
||||
|
||||
// make sure the information is propagated to sub aggregations
|
||||
String subFieldAgg = "{ \"my_outer_terms\": { \"terms\": { \"field\": \"f\" }, \"aggs\": " + fieldAgg + "}}";
|
||||
assertFalse(needsScores(index, subFieldAgg));
|
||||
|
||||
String subScriptAgg = "{ \"my_outer_terms\": { \"terms\": { \"field\": \"f\" }, \"aggs\": " + scriptAgg + "}}";
|
||||
assertTrue(needsScores(index, subScriptAgg));
|
||||
|
||||
// top_hits is a particular example of an aggregation that needs scores
|
||||
String topHitsAgg = "{ \"my_hits\": {\"top_hits\": {}}}";
|
||||
assertTrue(needsScores(index, topHitsAgg));
|
||||
}
|
||||
|
||||
private boolean needsScores(IndexService index, String agg) throws IOException {
|
||||
AggregatorParsers parser = getInstanceFromNode(AggregatorParsers.class);
|
||||
XContentParser aggParser = JsonXContent.jsonXContent.createParser(agg);
|
||||
aggParser.nextToken();
|
||||
final AggregatorFactories factories = parser.parseAggregators(aggParser, createSearchContext(index));
|
||||
return factories.needsScores();
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,9 @@ import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
|
||||
import org.elasticsearch.search.aggregations.AggregationPhase;
|
||||
import org.elasticsearch.search.aggregations.Aggregator;
|
||||
import org.elasticsearch.search.aggregations.AggregatorFactories;
|
||||
import org.elasticsearch.search.aggregations.SearchContextAggregations;
|
||||
import org.elasticsearch.search.aggregations.support.AggregationContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.test.ElasticsearchSingleNodeLuceneTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -113,11 +115,13 @@ public class NestedAggregatorTest extends ElasticsearchSingleNodeLuceneTestCase
|
||||
|
||||
IndexService indexService = createIndex("test");
|
||||
indexService.mapperService().merge("test", new CompressedString(PutMappingRequest.buildFromSimplifiedDef("test", "nested_field", "type=nested").string()), true);
|
||||
AggregationContext context = new AggregationContext(createSearchContext(indexService));
|
||||
SearchContext searchContext = createSearchContext(indexService);
|
||||
AggregationContext context = new AggregationContext(searchContext);
|
||||
|
||||
AggregatorFactories.Builder builder = AggregatorFactories.builder();
|
||||
builder.add(new NestedAggregator.Factory("test", "nested_field", FilterCachingPolicy.ALWAYS_CACHE));
|
||||
AggregatorFactories factories = builder.build();
|
||||
searchContext.aggregations(new SearchContextAggregations(factories));
|
||||
Aggregator[] aggs = factories.createTopLevelAggregators(context);
|
||||
AggregationPhase.AggregationsCollector collector = new AggregationPhase.AggregationsCollector(Arrays.asList(aggs), context);
|
||||
// A regular search always exclude nested docs, so we use NonNestedDocsFilter.INSTANCE here (otherwise MatchAllDocsQuery would be sufficient)
|
||||
|
@ -77,6 +77,7 @@ public class TestSearchContext extends SearchContext {
|
||||
int size;
|
||||
private int terminateAfter = DEFAULT_TERMINATE_AFTER;
|
||||
private String[] types;
|
||||
private SearchContextAggregations aggregations;
|
||||
|
||||
public TestSearchContext(ThreadPool threadPool,PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, IndexService indexService, FilterCache filterCache, IndexFieldDataService indexFieldDataService) {
|
||||
this.pageCacheRecycler = pageCacheRecycler;
|
||||
@ -143,7 +144,7 @@ public class TestSearchContext extends SearchContext {
|
||||
|
||||
@Override
|
||||
public int numberOfShards() {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,12 +184,13 @@ public class TestSearchContext extends SearchContext {
|
||||
|
||||
@Override
|
||||
public SearchContextAggregations aggregations() {
|
||||
return null;
|
||||
return aggregations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchContext aggregations(SearchContextAggregations aggregations) {
|
||||
return null;
|
||||
this.aggregations = aggregations;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,7 +299,7 @@ public class TestSearchContext extends SearchContext {
|
||||
|
||||
@Override
|
||||
public ScriptService scriptService() {
|
||||
return null;
|
||||
return indexService.injector().getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -529,7 +531,7 @@ public class TestSearchContext extends SearchContext {
|
||||
|
||||
@Override
|
||||
public SearchLookup lookup() {
|
||||
return null;
|
||||
return new SearchLookup(mapperService(), fieldData(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user