Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,15 @@ protected static final class WeightOrDocIdSetIterator {
protected abstract static class RewritingWeight extends ConstantScoreWeight {
private final MultiTermQuery q;
private final ScoreMode scoreMode;
private final IndexSearcher searcher;
private final IndexSearcher nonCachingSearcher;

protected RewritingWeight(
MultiTermQuery q, float boost, ScoreMode scoreMode, IndexSearcher searcher) {
super(q, boost);
this.q = q;
this.scoreMode = scoreMode;
this.searcher = searcher;
this.nonCachingSearcher = new IndexSearcher(searcher);
this.nonCachingSearcher.setQueryCache(null);
}

/**
Expand All @@ -158,12 +159,13 @@ private WeightOrDocIdSetIterator rewriteAsBooleanQuery(
LeafReaderContext context, List<TermAndState> collectedTerms) throws IOException {
BooleanQuery.Builder bq = new BooleanQuery.Builder();
for (TermAndState t : collectedTerms) {
final TermStates termStates = new TermStates(searcher.getTopReaderContext());
final TermStates termStates = new TermStates(nonCachingSearcher.getTopReaderContext());
termStates.register(t.state, context.ord, t.docFreq, t.totalTermFreq);
bq.add(new TermQuery(new Term(q.field, t.term), termStates), BooleanClause.Occur.SHOULD);
}
Query q = new ConstantScoreQuery(bq.build());
final Weight weight = searcher.rewrite(q).createWeight(searcher, scoreMode, score());
final Weight weight =
nonCachingSearcher.rewrite(q).createWeight(nonCachingSearcher, scoreMode, score());
return new WeightOrDocIdSetIterator(weight);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@ public IndexSearcher(IndexReaderContext context) {
this(context, null);
}

/** Reuses everything except the executor */
public IndexSearcher(IndexSearcher searcher) {
this(searcher.getTopReaderContext());
this.similarity = searcher.getSimilarity();
this.queryCache = searcher.getQueryCache();
this.queryCachingPolicy = searcher.getQueryCachingPolicy();
this.queryTimeout = searcher.getTimeout();
}

/**
* Return the maximum number of clauses permitted, 1024 by default. Attempts to add more than the
* permitted number of clauses cause {@link TooManyClauses} to be thrown.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,71 @@

public class TestTermInSetQuery extends LuceneTestCase {

public void testCachingPolicyInteraction() throws IOException {
Directory dir = newDirectory();
RandomIndexWriter iw = new RandomIndexWriter(random(), dir);
// Use few enough terms to trigger the BooleanQuery rewrite logic (≤ threshold)
final int numTerms =
AbstractMultiTermQueryConstantScoreWrapper.BOOLEAN_REWRITE_TERM_COUNT_THRESHOLD;
List<BytesRef> terms = new ArrayList<>();
for (int i = 0; i < numTerms; ++i) {
String term = "term" + i;
terms.add(newBytesRef(term));
Document doc = new Document();
doc.add(new StringField("field", term, Store.NO));
iw.addDocument(doc);
}
iw.commit();
IndexReader reader = iw.getReader();
IndexSearcher searcher = newSearcher(reader);
iw.close();

final AtomicInteger onUseCount = new AtomicInteger(0);
final Set<Query> seenQueries = new HashSet<>();
QueryCachingPolicy policy =
new QueryCachingPolicy() {
@Override
public void onUse(Query query) {
onUseCount.incrementAndGet();
seenQueries.add(query);
}

@Override
public boolean shouldCache(Query query) throws IOException {
return true;
}
};

searcher.setQueryCache(new LRUQueryCache(100, 10000));
searcher.setQueryCachingPolicy(policy);

TermInSetQuery query = new TermInSetQuery("field", terms);
// use count() to ensure scores are not needed, which triggers caching logic
searcher.count(query);

// We expect only the top-level TermInSetQuery to be tracked.
// The inner rewrites (ConstantScoreQuery wrapping BooleanQuery) should
// effectively bypass the
// cache because they are executed by the non-caching private searcher.
// Verify that no BooleanQuery or ConstantScoreQuery wrapping BooleanQuery was
// tracked
assertFalse(
"Segment-specific BooleanQuery rewrites should not be tracked",
seenQueries.stream().anyMatch(q -> q instanceof BooleanQuery));
assertFalse(
"ConstantScoreQuery wrapping BooleanQuery should not be tracked",
seenQueries.stream()
.anyMatch(
q ->
q instanceof ConstantScoreQuery
&& ((ConstantScoreQuery) q).getQuery() instanceof BooleanQuery));
// The TermInSetQuery itself should be tracked
assertTrue("TermInSetQuery should be tracked", seenQueries.contains(query));

reader.close();
dir.close();
}

public void testAllDocsInFieldTerm() throws IOException {
Directory dir = newDirectory();
RandomIndexWriter iw = new RandomIndexWriter(random(), dir);
Expand Down
Loading