QueryWrapperFilter discards the IndexReaderContext when delegating to the wrapped query [LUCENE-6503]
- Dominant language
- Java
- Stars
- 3.6k
- Forks
- 1.4k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 88
Description
Suppose I have a working `Filter` which depends on the context within the composite reader, e.g., one which has a global BitSet of the docs which match but needs to know the docBase and maxDoc for the individual reader in order to return the correct set to the caller.
This is wrapped into a `ConstantScoreQuery` in order to become part of a `BooleanQuery` tree.
At some other layer, the entire query tree is wrapped back into a `QueryWrapperFilter` by some other code which wants to cache the results as a Filter.
QueryWrapperFilter has code like this:
```Java
`@Override`
public DocIdSet getDocIdSet(final AtomicReaderContext context, final Bits acceptDocs) throws IOException {
// get a private context that is used to rewrite, createWeight and score eventually
final AtomicReaderContext privateContext = context.reader().getContext();
final Weight weight = new IndexSearcher(privateContext).createNormalizedWeight(query);
return new DocIdSet() {
`@Override`
public DocIdSetIterator iterator() throws IOException {
return weight.scorer(privateContext, acceptDocs);
}
`@Override`
public boolean isCacheable() { return false; }
};
}
```
The call to `reader().getContext()` returns an `AtomicReaderContext` whose parent is not correctly set.
This is then passed to `Weight#scorer` which eventually arrives at `ConstantScoreQuery#scorer`, which calls `Filter#getDocIdSet`.
So our innermost `Filter` receives an `AtomicReaderContext` whose top-level `IndexReader` is not the actual top-level reader. This was detected in our code because we use a special subclass of DirectoryReader for our top-level reader and thus the filter failed. (Had it not failed, it would have silently returned the wrong results.)
The fix I have applied locally is to change the call to:
```Java
return weight.scorer(context, acceptDocs);
```
This does appear to be working, but I'm not really sure if it's OK to build the IndexSearcher using one context while passing another context to the scorer.
---
Migrated from [LUCENE-6503](https://issues.apache.org/jira/browse/LUCENE-6503) by Trejkaz
Contributor guide
Research direction
Start at QueryWrapperFilter#getDocIdSet and trace Weight#scorer through ConstantScoreQuery#scorer to Filter#getDocIdSet. Compare the private context from reader().getContext() with the original AtomicReaderContext, and determine whether the scorer receives the correct top-level reader while the searcher is built. Done means wrapped filters consistently receive the original context without breaking scoring behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- search
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100