Make ContextIndexSearcher delegate more method calls to Engine.searcher().
When running tests, Engine.searcher() is going to be an AssertingIndexSearcher so we definitely don't want to discard it. This commit fixes it as well as the bugs it found. Closes #3987
This commit is contained in:
parent
ce891e93b6
commit
2e8bbe9e30
|
@ -0,0 +1,250 @@
|
|||
package org.apache.lucene.search;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF 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.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.index.AtomicReaderContext;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Extension of {@link ConstantScoreQuery} that works around LUCENE-5307.
|
||||
*/
|
||||
// we extend CSQ so that highlighters know how to deal with this query
|
||||
public class XLuceneConstantScoreQuery extends ConstantScoreQuery {
|
||||
|
||||
static {
|
||||
assert Version.LUCENE_45.onOrAfter(Lucene.VERSION) : "Lucene 4.6 CSQ is fixed, remove this one!";
|
||||
}
|
||||
|
||||
public XLuceneConstantScoreQuery(Query filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
public XLuceneConstantScoreQuery(Filter filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
if (query != null) {
|
||||
Query rewritten = query.rewrite(reader);
|
||||
if (rewritten != query) {
|
||||
rewritten = new XLuceneConstantScoreQuery(rewritten);
|
||||
rewritten.setBoost(this.getBoost());
|
||||
return rewritten;
|
||||
}
|
||||
} else {
|
||||
assert filter != null;
|
||||
// Fix outdated usage pattern from Lucene 2.x/early-3.x:
|
||||
// because ConstantScoreQuery only accepted filters,
|
||||
// QueryWrapperFilter was used to wrap queries.
|
||||
if (filter instanceof QueryWrapperFilter) {
|
||||
final QueryWrapperFilter qwf = (QueryWrapperFilter) filter;
|
||||
final Query rewritten = new XLuceneConstantScoreQuery(qwf.getQuery().rewrite(reader));
|
||||
rewritten.setBoost(this.getBoost());
|
||||
return rewritten;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weight createWeight(IndexSearcher searcher) throws IOException {
|
||||
return new XConstantWeight(searcher);
|
||||
}
|
||||
|
||||
protected class XConstantWeight extends Weight {
|
||||
private final Weight innerWeight;
|
||||
private float queryNorm;
|
||||
private float queryWeight;
|
||||
|
||||
public XConstantWeight(IndexSearcher searcher) throws IOException {
|
||||
this.innerWeight = (query == null) ? null : query.createWeight(searcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getQuery() {
|
||||
return XLuceneConstantScoreQuery.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValueForNormalization() throws IOException {
|
||||
// we calculate sumOfSquaredWeights of the inner weight, but ignore it (just to initialize everything)
|
||||
if (innerWeight != null) innerWeight.getValueForNormalization();
|
||||
queryWeight = getBoost();
|
||||
return queryWeight * queryWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalize(float norm, float topLevelBoost) {
|
||||
this.queryNorm = norm * topLevelBoost;
|
||||
queryWeight *= this.queryNorm;
|
||||
// we normalize the inner weight, but ignore it (just to initialize everything)
|
||||
if (innerWeight != null) innerWeight.normalize(norm, topLevelBoost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
|
||||
boolean topScorer, final Bits acceptDocs) throws IOException {
|
||||
final DocIdSetIterator disi;
|
||||
if (filter != null) {
|
||||
assert query == null;
|
||||
final DocIdSet dis = filter.getDocIdSet(context, acceptDocs);
|
||||
if (dis == null) {
|
||||
return null;
|
||||
}
|
||||
disi = dis.iterator();
|
||||
} else {
|
||||
assert query != null && innerWeight != null;
|
||||
disi = innerWeight.scorer(context, scoreDocsInOrder, topScorer, acceptDocs);
|
||||
}
|
||||
|
||||
if (disi == null) {
|
||||
return null;
|
||||
}
|
||||
return new XConstantScorer(disi, this, queryWeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scoresDocsOutOfOrder() {
|
||||
return (innerWeight != null) ? innerWeight.scoresDocsOutOfOrder() : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Explanation explain(AtomicReaderContext context, int doc) throws IOException {
|
||||
final Scorer cs = scorer(context, true, false, context.reader().getLiveDocs());
|
||||
final boolean exists = (cs != null && cs.advance(doc) == doc);
|
||||
|
||||
final ComplexExplanation result = new ComplexExplanation();
|
||||
if (exists) {
|
||||
result.setDescription(XLuceneConstantScoreQuery.this.toString() + ", product of:");
|
||||
result.setValue(queryWeight);
|
||||
result.setMatch(Boolean.TRUE);
|
||||
result.addDetail(new Explanation(getBoost(), "boost"));
|
||||
result.addDetail(new Explanation(queryNorm, "queryNorm"));
|
||||
} else {
|
||||
result.setDescription(XLuceneConstantScoreQuery.this.toString() + " doesn't match id " + doc);
|
||||
result.setValue(0);
|
||||
result.setMatch(Boolean.FALSE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected class XConstantScorer extends Scorer {
|
||||
final DocIdSetIterator docIdSetIterator;
|
||||
final float theScore;
|
||||
|
||||
public XConstantScorer(DocIdSetIterator docIdSetIterator, Weight w, float theScore) {
|
||||
super(w);
|
||||
this.theScore = theScore;
|
||||
this.docIdSetIterator = docIdSetIterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
return docIdSetIterator.nextDoc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int docID() {
|
||||
return docIdSetIterator.docID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float score() throws IOException {
|
||||
assert docIdSetIterator.docID() != NO_MORE_DOCS;
|
||||
return theScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
return docIdSetIterator.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docIdSetIterator.cost();
|
||||
}
|
||||
|
||||
private Collector wrapCollector(final Collector collector) {
|
||||
return new Collector() {
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
// we must wrap again here, but using the scorer passed in as parameter:
|
||||
collector.setScorer(new ConstantScorer(scorer, XConstantScorer.this.weight, XConstantScorer.this.theScore));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
collector.collect(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextReader(AtomicReaderContext context) throws IOException {
|
||||
collector.setNextReader(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsDocsOutOfOrder() {
|
||||
return collector.acceptsDocsOutOfOrder();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// this optimization allows out of order scoring as top scorer!
|
||||
@Override
|
||||
public void score(Collector collector) throws IOException {
|
||||
if (query != null) {
|
||||
((Scorer) docIdSetIterator).score(wrapCollector(collector));
|
||||
} else {
|
||||
super.score(collector);
|
||||
}
|
||||
}
|
||||
|
||||
// this optimization allows out of order scoring as top scorer,
|
||||
@Override
|
||||
public boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
if (query != null) {
|
||||
return ((Scorer) docIdSetIterator).score(wrapCollector(collector), max, firstDocID);
|
||||
} else {
|
||||
return super.score(collector, max, firstDocID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChildScorer> getChildren() {
|
||||
if (query != null)
|
||||
return Collections.singletonList(new ChildScorer((Scorer) docIdSetIterator, "constant"));
|
||||
else
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -116,7 +116,7 @@ public class Lucene {
|
|||
TotalHitCountCollector countCollector = new TotalHitCountCollector();
|
||||
// we don't need scores, so wrap it in a constant score query
|
||||
if (!(query instanceof ConstantScoreQuery)) {
|
||||
query = new ConstantScoreQuery(query);
|
||||
query = new XLuceneConstantScoreQuery(query);
|
||||
}
|
||||
searcher.search(query, countCollector);
|
||||
return countCollector.getTotalHits();
|
||||
|
|
|
@ -29,33 +29,36 @@ import java.io.IOException;
|
|||
*/
|
||||
public class EmptyScorer extends Scorer {
|
||||
|
||||
private int docId = -1;
|
||||
|
||||
public EmptyScorer(Weight weight) {
|
||||
super(weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float score() throws IOException {
|
||||
return 0;
|
||||
throw new UnsupportedOperationException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
return 0;
|
||||
throw new UnsupportedOperationException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int docID() {
|
||||
return -1;
|
||||
return docId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
return NO_MORE_DOCS;
|
||||
assert docId != NO_MORE_DOCS;
|
||||
return docId = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
return NO_MORE_DOCS;
|
||||
return slowAdvance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,14 +32,6 @@ import java.util.Set;
|
|||
*/
|
||||
public final class MatchNoDocsQuery extends Query {
|
||||
|
||||
public static MatchNoDocsQuery INSTANCE = new MatchNoDocsQuery();
|
||||
|
||||
/**
|
||||
* Since all instances of this class are equal to each other,
|
||||
* we have a constant hash code.
|
||||
*/
|
||||
private static final int HASH_CODE = 12345;
|
||||
|
||||
/**
|
||||
* Weight implementation that matches no documents.
|
||||
*/
|
||||
|
@ -92,11 +84,14 @@ public final class MatchNoDocsQuery extends Query {
|
|||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return o instanceof MatchAllDocsQuery;
|
||||
if (o instanceof MatchNoDocsQuery) {
|
||||
return getBoost() == ((MatchNoDocsQuery) o).getBoost();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HASH_CODE;
|
||||
return getClass().hashCode() ^ Float.floatToIntBits(getBoost());
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ import org.apache.lucene.search.similarities.TFIDFSimilarity;
|
|||
import org.elasticsearch.common.io.FastStringReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -67,6 +68,68 @@ public class MoreLikeThisQuery extends Query {
|
|||
this.analyzer = analyzer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = boostTerms ? 1 : 0;
|
||||
result = 31 * result + Float.floatToIntBits(boostTermsFactor);
|
||||
result = 31 * result + likeText.hashCode();
|
||||
result = 31 * result + maxDocFreq;
|
||||
result = 31 * result + maxQueryTerms;
|
||||
result = 31 * result + maxWordLen;
|
||||
result = 31 * result + minDocFreq;
|
||||
result = 31 * result + minTermFrequency;
|
||||
result = 31 * result + minWordLen;
|
||||
result = 31 * result + Arrays.hashCode(moreLikeFields);
|
||||
result = 31 * result + Float.floatToIntBits(percentTermsToMatch);
|
||||
result = 31 * result + (stopWords == null ? 0 : stopWords.hashCode());
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
MoreLikeThisQuery other = (MoreLikeThisQuery) obj;
|
||||
if (getBoost() != other.getBoost())
|
||||
return false;
|
||||
if (!analyzer.equals(other.analyzer))
|
||||
return false;
|
||||
if (boostTerms != other.boostTerms)
|
||||
return false;
|
||||
if (boostTermsFactor != other.boostTermsFactor)
|
||||
return false;
|
||||
if (!likeText.equals(other.likeText))
|
||||
return false;
|
||||
if (maxDocFreq != other.maxDocFreq)
|
||||
return false;
|
||||
if (maxQueryTerms != other.maxQueryTerms)
|
||||
return false;
|
||||
if (maxWordLen != other.maxWordLen)
|
||||
return false;
|
||||
if (minDocFreq != other.minDocFreq)
|
||||
return false;
|
||||
if (minTermFrequency != other.minTermFrequency)
|
||||
return false;
|
||||
if (minWordLen != other.minWordLen)
|
||||
return false;
|
||||
if (!Arrays.equals(moreLikeFields, other.moreLikeFields))
|
||||
return false;
|
||||
if (percentTermsToMatch != other.percentTermsToMatch)
|
||||
return false;
|
||||
if (similarity == null) {
|
||||
if (other.similarity != null)
|
||||
return false;
|
||||
} else if (!similarity.equals(other.similarity))
|
||||
return false;
|
||||
if (stopWords == null) {
|
||||
if (other.stopWords != null)
|
||||
return false;
|
||||
} else if (!stopWords.equals(other.stopWords))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
MoreLikeThis mlt = new MoreLikeThis(reader, similarity == null ? new DefaultSimilarity() : similarity);
|
||||
|
@ -212,4 +275,3 @@ public class MoreLikeThisQuery extends Query {
|
|||
this.boostTermsFactor = boostTermsFactor;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ public class MultiPhrasePrefixQuery extends Query {
|
|||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
if (termArrays.isEmpty()) {
|
||||
return MatchNoDocsQuery.INSTANCE;
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
MultiPhraseQuery query = new MultiPhraseQuery();
|
||||
query.setSlop(slop);
|
||||
|
@ -146,7 +146,7 @@ public class MultiPhrasePrefixQuery extends Query {
|
|||
}
|
||||
}
|
||||
if (terms.isEmpty()) {
|
||||
return MatchNoDocsQuery.INSTANCE;
|
||||
return Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
query.add(terms.toArray(Term.class), position);
|
||||
return query.rewrite(reader);
|
||||
|
|
|
@ -33,10 +33,6 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
public class Queries {
|
||||
|
||||
/* In general we should never us a static query instance and share it.
|
||||
* In this case the instance is immutable so that's ok.*/
|
||||
public final static Query NO_MATCH_QUERY = MatchNoDocsQuery.INSTANCE;
|
||||
|
||||
/**
|
||||
* A match all docs filter. Note, requires no caching!.
|
||||
*/
|
||||
|
@ -50,6 +46,11 @@ public class Queries {
|
|||
return new XConstantScoreQuery(MATCH_ALL_FILTER);
|
||||
}
|
||||
|
||||
/** Return a query that matches no document. */
|
||||
public static Query newMatchNoDocsQuery() {
|
||||
return new MatchNoDocsQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimizes the given query and returns the optimized version of it.
|
||||
*/
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.elasticsearch.common.lucene.search;
|
||||
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.XLuceneConstantScoreQuery;
|
||||
|
||||
/**
|
||||
* We still need sometimes to exclude deletes, because we don't remove them always with acceptDocs on filters
|
||||
*/
|
||||
public class XConstantScoreQuery extends ConstantScoreQuery {
|
||||
public class XConstantScoreQuery extends XLuceneConstantScoreQuery {
|
||||
|
||||
private final Filter actualFilter;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ import java.util.Set;
|
|||
*/
|
||||
// Changes are marked with //CHANGE:
|
||||
// Delegate to FilteredQuery - this version fixes the bug in LUCENE-4705 and uses ApplyAcceptedDocsFilter internally
|
||||
public class XFilteredQuery extends Query {
|
||||
public final class XFilteredQuery extends Query {
|
||||
private final Filter rawFilter;
|
||||
private final FilteredQuery delegate;
|
||||
private final FilterStrategy strategy;
|
||||
|
@ -67,7 +67,11 @@ public class XFilteredQuery extends Query {
|
|||
* @see FilterStrategy
|
||||
*/
|
||||
public XFilteredQuery(Query query, Filter filter, FilterStrategy strategy) {
|
||||
delegate = new FilteredQuery(query, new ApplyAcceptedDocsFilter(filter), strategy);
|
||||
this(new FilteredQuery(query, new ApplyAcceptedDocsFilter(filter), strategy), filter, strategy);
|
||||
}
|
||||
|
||||
private XFilteredQuery(FilteredQuery delegate, Filter filter, FilterStrategy strategy) {
|
||||
this.delegate = delegate;
|
||||
// CHANGE: we need to wrap it in post application of accepted docs
|
||||
this.rawFilter = filter;
|
||||
this.strategy = strategy;
|
||||
|
@ -96,7 +100,7 @@ public class XFilteredQuery extends Query {
|
|||
if (queryRewritten instanceof MatchAllDocsQuery || Queries.isConstantMatchAllQuery(queryRewritten)) {
|
||||
// Special case: If the query is a MatchAllDocsQuery, we only
|
||||
// return a CSQ(filter).
|
||||
final Query rewritten = new ConstantScoreQuery(delegate.getFilter());
|
||||
final Query rewritten = new XLuceneConstantScoreQuery(delegate.getFilter());
|
||||
// Combine boost of MatchAllDocsQuery and the wrapped rewritten query:
|
||||
rewritten.setBoost(delegate.getBoost() * queryRewritten.getBoost());
|
||||
return rewritten;
|
||||
|
@ -249,4 +253,9 @@ public class XFilteredQuery extends Query {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query clone() {
|
||||
return new XFilteredQuery((FilteredQuery) delegate.clone(), rawFilter, strategy);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ public class FiltersFunctionScoreQuery extends Query {
|
|||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (getClass() != o.getClass())
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
FiltersFunctionScoreQuery other = (FiltersFunctionScoreQuery) o;
|
||||
if (this.getBoost() != other.getBoost())
|
||||
|
|
|
@ -191,7 +191,7 @@ public class FunctionScoreQuery extends Query {
|
|||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (getClass() != o.getClass())
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
FunctionScoreQuery other = (FunctionScoreQuery) o;
|
||||
return this.getBoost() == other.getBoost() && this.subQuery.equals(other.subQuery) && this.function.equals(other.function)
|
||||
|
|
|
@ -170,7 +170,7 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
|
|||
return super.termQuery(value, context);
|
||||
}
|
||||
// no need for constant score filter, since we don't cache the filter, and it always takes deletes into account
|
||||
return new ConstantScoreQuery(termFilter(value, context));
|
||||
return new XLuceneConstantScoreQuery(termFilter(value, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,9 +25,9 @@ import org.apache.lucene.index.FieldInfo.IndexOptions;
|
|||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queries.TermFilter;
|
||||
import org.apache.lucene.queries.TermsFilter;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.XLuceneConstantScoreQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
@ -249,7 +249,7 @@ public class ParentFieldMapper extends AbstractFieldMapper<Uid> implements Inter
|
|||
if (context == null) {
|
||||
return super.termQuery(value, context);
|
||||
}
|
||||
return new ConstantScoreQuery(termFilter(value, context));
|
||||
return new XLuceneConstantScoreQuery(termFilter(value, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.XLuceneConstantScoreQuery;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
|
||||
|
@ -104,7 +104,7 @@ public class ConstantScoreQueryParser implements QueryParser {
|
|||
return query1;
|
||||
}
|
||||
// Query
|
||||
query = new ConstantScoreQuery(query);
|
||||
query = new XLuceneConstantScoreQuery(query);
|
||||
query.setBoost(boost);
|
||||
return query;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ package org.elasticsearch.index.query;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.apache.lucene.queries.TermsFilter;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.XLuceneConstantScoreQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
|
@ -106,7 +106,7 @@ public class IdsQueryParser implements QueryParser {
|
|||
}
|
||||
|
||||
if (ids.isEmpty()) {
|
||||
return Queries.NO_MATCH_QUERY;
|
||||
return Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
|
||||
if (types == null || types.isEmpty()) {
|
||||
|
@ -117,7 +117,7 @@ public class IdsQueryParser implements QueryParser {
|
|||
|
||||
TermsFilter filter = new TermsFilter(UidFieldMapper.NAME, Uid.createTypeUids(types, ids));
|
||||
// no need for constant score filter, since we don't cache the filter, and it always takes deletes into account
|
||||
ConstantScoreQuery query = new ConstantScoreQuery(filter);
|
||||
XLuceneConstantScoreQuery query = new XLuceneConstantScoreQuery(filter);
|
||||
query.setBoost(boost);
|
||||
if (queryName != null) {
|
||||
parseContext.addNamedQuery(queryName, query);
|
||||
|
|
|
@ -283,7 +283,7 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
parseContext.reset(parser);
|
||||
Query query = parseContext.parseInnerQuery();
|
||||
if (query == null) {
|
||||
query = Queries.NO_MATCH_QUERY;
|
||||
query = Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
return new ParsedQuery(query, parseContext.copyNamedFilters());
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ public class IndicesQueryParser implements QueryParser {
|
|||
if ("all".equals(type)) {
|
||||
noMatchQuery = Queries.newMatchAllQuery();
|
||||
} else if ("none".equals(type)) {
|
||||
noMatchQuery = MatchNoDocsQuery.INSTANCE;
|
||||
noMatchQuery = Queries.newMatchNoDocsQuery();
|
||||
}
|
||||
} else if ("_name".equals(currentFieldName)) {
|
||||
queryName = parser.text();
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.apache.lucene.util.UnicodeUtil;
|
|||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||
import org.elasticsearch.ElasticSearchIllegalStateException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
|
||||
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
|
@ -390,6 +389,6 @@ public class MatchQuery {
|
|||
}
|
||||
|
||||
protected Query zeroTermsQuery() {
|
||||
return zeroTermsQuery == ZeroTermsQuery.NONE ? MatchNoDocsQuery.INSTANCE : Queries.newMatchAllQuery();
|
||||
return zeroTermsQuery == ZeroTermsQuery.NONE ? Queries.newMatchNoDocsQuery() : Queries.newMatchAllQuery();
|
||||
}
|
||||
}
|
|
@ -101,7 +101,7 @@ public class ChildrenConstantScoreQuery extends Query {
|
|||
|
||||
int remaining = collectedUids.v().size();
|
||||
if (remaining == 0) {
|
||||
return Queries.NO_MATCH_QUERY.createWeight(searcher);
|
||||
return Queries.newMatchNoDocsQuery().createWeight(searcher);
|
||||
}
|
||||
|
||||
Filter shortCircuitFilter = null;
|
||||
|
@ -261,6 +261,9 @@ public class ChildrenConstantScoreQuery extends Query {
|
|||
if (shortCircuitParentDocSet != that.shortCircuitParentDocSet) {
|
||||
return false;
|
||||
}
|
||||
if (getBoost() != that.getBoost()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -268,7 +271,8 @@ public class ChildrenConstantScoreQuery extends Query {
|
|||
public int hashCode() {
|
||||
int result = originalChildQuery.hashCode();
|
||||
result = 31 * result + childType.hashCode();
|
||||
result += shortCircuitParentDocSet;
|
||||
result = 31 * result + shortCircuitParentDocSet;
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,9 @@ public class ChildrenQuery extends Query {
|
|||
if (!childType.equals(that.childType)) {
|
||||
return false;
|
||||
}
|
||||
if (getBoost() != that.getBoost()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -99,6 +102,7 @@ public class ChildrenQuery extends Query {
|
|||
public int hashCode() {
|
||||
int result = originalChildQuery.hashCode();
|
||||
result = 31 * result + childType.hashCode();
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -158,7 +162,7 @@ public class ChildrenQuery extends Query {
|
|||
if (uidToCount != null) {
|
||||
uidToCount.release();
|
||||
}
|
||||
return Queries.NO_MATCH_QUERY.createWeight(searcher);
|
||||
return Queries.newMatchNoDocsQuery().createWeight(searcher);
|
||||
}
|
||||
|
||||
Filter parentFilter;
|
||||
|
|
|
@ -99,7 +99,7 @@ public class ParentConstantScoreQuery extends Query {
|
|||
indexSearcher.search(parentQuery, collector);
|
||||
|
||||
if (parents.v().isEmpty()) {
|
||||
return Queries.NO_MATCH_QUERY.createWeight(searcher);
|
||||
return Queries.newMatchNoDocsQuery().createWeight(searcher);
|
||||
}
|
||||
|
||||
ChildrenWeight childrenWeight = new ChildrenWeight(searchContext, parents);
|
||||
|
@ -219,6 +219,7 @@ public class ParentConstantScoreQuery extends Query {
|
|||
public int hashCode() {
|
||||
int result = originalParentQuery.hashCode();
|
||||
result = 31 * result + parentType.hashCode();
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -238,6 +239,9 @@ public class ParentConstantScoreQuery extends Query {
|
|||
if (!parentType.equals(that.parentType)) {
|
||||
return false;
|
||||
}
|
||||
if (this.getBoost() != that.getBoost()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ public class ParentQuery extends Query {
|
|||
if (!parentType.equals(that.parentType)) {
|
||||
return false;
|
||||
}
|
||||
if (getBoost() != that.getBoost()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -85,6 +88,7 @@ public class ParentQuery extends Query {
|
|||
public int hashCode() {
|
||||
int result = originalParentQuery.hashCode();
|
||||
result = 31 * result + parentType.hashCode();
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -131,7 +135,7 @@ public class ParentQuery extends Query {
|
|||
|
||||
if (uidToScore.v().isEmpty()) {
|
||||
uidToScore.release();
|
||||
return Queries.NO_MATCH_QUERY.createWeight(searcher);
|
||||
return Queries.newMatchNoDocsQuery().createWeight(searcher);
|
||||
}
|
||||
|
||||
ChildWeight childWeight = new ChildWeight(parentQuery.createWeight(searcher), searchContext, uidToScore);
|
||||
|
|
|
@ -230,6 +230,9 @@ public class TopChildrenQuery extends Query {
|
|||
if (incrementalFactor != that.incrementalFactor) {
|
||||
return false;
|
||||
}
|
||||
if (getBoost() != that.getBoost()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -238,6 +241,7 @@ public class TopChildrenQuery extends Query {
|
|||
int result = originalChildQuery.hashCode();
|
||||
result = 31 * result + parentType.hashCode();
|
||||
result = 31 * result + incrementalFactor;
|
||||
result = 31 * result + Float.floatToIntBits(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -342,10 +346,7 @@ public class TopChildrenQuery extends Query {
|
|||
|
||||
@Override
|
||||
public final int advance(int target) throws IOException {
|
||||
int doc;
|
||||
while ((doc = nextDoc()) < target) {
|
||||
}
|
||||
return doc;
|
||||
return slowAdvance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -129,6 +129,8 @@ public class QueryFacetExecutor extends FacetExecutor {
|
|||
if (constantScoreQuery.getFilter() != null) {
|
||||
return constantScoreQuery.getFilter();
|
||||
}
|
||||
} else if (query instanceof XLuceneConstantScoreQuery) {
|
||||
return ((XLuceneConstantScoreQuery) query).getFilter();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Context-aware extension of {@link IndexSearcher}.
|
||||
*/
|
||||
public class ContextIndexSearcher extends IndexSearcher {
|
||||
|
||||
|
@ -43,6 +43,11 @@ public class ContextIndexSearcher extends IndexSearcher {
|
|||
MAIN_QUERY
|
||||
}
|
||||
|
||||
/** The wrapped {@link IndexSearcher}. The reason why we sometimes prefer delegating to this searcher instead of <tt>super</tt> is that
|
||||
* this instance may have more assertions, for example if it comes from MockRobinEngine which wraps the IndexSearcher into an
|
||||
* AssertingIndexSearcher. */
|
||||
private final IndexSearcher in;
|
||||
|
||||
private final SearchContext searchContext;
|
||||
|
||||
private CachedDfSource dfSource;
|
||||
|
@ -56,6 +61,7 @@ public class ContextIndexSearcher extends IndexSearcher {
|
|||
|
||||
public ContextIndexSearcher(SearchContext searchContext, Engine.Searcher searcher) {
|
||||
super(searcher.reader());
|
||||
in = searcher.searcher();
|
||||
this.searchContext = searchContext;
|
||||
setSimilarity(searcher.searcher().getSimilarity());
|
||||
}
|
||||
|
@ -106,11 +112,11 @@ public class ContextIndexSearcher extends IndexSearcher {
|
|||
if (searchContext.queryRewritten()) {
|
||||
return searchContext.query();
|
||||
}
|
||||
Query rewriteQuery = super.rewrite(original);
|
||||
Query rewriteQuery = in.rewrite(original);
|
||||
searchContext.updateRewriteQuery(rewriteQuery);
|
||||
return rewriteQuery;
|
||||
} else {
|
||||
return super.rewrite(original);
|
||||
return in.rewrite(original);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +127,7 @@ public class ContextIndexSearcher extends IndexSearcher {
|
|||
if (dfSource != null && (query == searchContext.query() || query == searchContext.parsedQuery().query())) {
|
||||
return dfSource.createNormalizedWeight(query);
|
||||
}
|
||||
return super.createNormalizedWeight(query);
|
||||
return in.createNormalizedWeight(query);
|
||||
} catch (Throwable t) {
|
||||
searchContext.clearReleasables();
|
||||
throw new RuntimeException(t);
|
||||
|
|
|
@ -24,10 +24,10 @@ import org.apache.lucene.document.Field;
|
|||
import org.apache.lucene.document.TextField;
|
||||
import org.apache.lucene.index.*;
|
||||
import org.apache.lucene.queries.TermFilter;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.XLuceneConstantScoreQuery;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
|
@ -41,7 +41,6 @@ import org.junit.Test;
|
|||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.Builder.EMPTY_SETTINGS;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
|
@ -68,7 +67,7 @@ public class FilterCacheTests extends ElasticsearchTestCase {
|
|||
|
||||
reader = refreshReader(reader);
|
||||
IndexSearcher searcher = new IndexSearcher(reader);
|
||||
assertThat(Lucene.count(searcher, new ConstantScoreQuery(filterCache.cache(new TermFilter(new Term("id", "1"))))), equalTo(1l));
|
||||
assertThat(Lucene.count(searcher, new XLuceneConstantScoreQuery(filterCache.cache(new TermFilter(new Term("id", "1"))))), equalTo(1l));
|
||||
assertThat(Lucene.count(searcher, new XFilteredQuery(new MatchAllDocsQuery(), filterCache.cache(new TermFilter(new Term("id", "1"))))), equalTo(1l));
|
||||
|
||||
indexWriter.deleteDocuments(new Term("id", "1"));
|
||||
|
@ -78,7 +77,7 @@ public class FilterCacheTests extends ElasticsearchTestCase {
|
|||
Filter cachedFilter = filterCache.cache(filter);
|
||||
long constantScoreCount = filter == cachedFilter ? 0 : 1;
|
||||
// sadly, when caching based on cacheKey with NRT, this fails, that's why we have DeletionAware one
|
||||
assertThat(Lucene.count(searcher, new ConstantScoreQuery(cachedFilter)), equalTo(constantScoreCount));
|
||||
assertThat(Lucene.count(searcher, new XLuceneConstantScoreQuery(cachedFilter)), equalTo(constantScoreCount));
|
||||
assertThat(Lucene.count(searcher, new XConstantScoreQuery(cachedFilter)), equalTo(0l));
|
||||
assertThat(Lucene.count(searcher, new XFilteredQuery(new MatchAllDocsQuery(), cachedFilter)), equalTo(0l));
|
||||
|
||||
|
|
|
@ -317,8 +317,8 @@ public class SimpleIndexQueryParserTests extends ElasticsearchTestCase {
|
|||
IndexQueryParserService queryParser = queryParser();
|
||||
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/starColonStar.json");
|
||||
Query parsedQuery = queryParser.parse(query).query();
|
||||
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
|
||||
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
|
||||
assertThat(parsedQuery, instanceOf(XLuceneConstantScoreQuery.class));
|
||||
XLuceneConstantScoreQuery constantScoreQuery = (XLuceneConstantScoreQuery) parsedQuery;
|
||||
Filter internalFilter = constantScoreQuery.getFilter();
|
||||
assertThat(internalFilter, instanceOf(MatchAllDocsFilter.class));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue