LUCENE-6290: Make the filter -> query migration less trappy.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1662203 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Adrien Grand 2015-02-25 12:07:58 +00:00
parent 732f9aeecc
commit 822068e56b
6 changed files with 113 additions and 4 deletions

View File

@ -108,6 +108,10 @@ Optimizations
in order to advance doc IDs, which takes advantage of the cost() API.
(Adrien Grand)
* LUCENE-6290: QueryWrapperFilter propagates approximations and FilteredQuery
rewrites to a BooleanQuery when the filter is a QueryWrapperFilter in order
to leverage approximations. (Adrien Grand)
API Changes
* LUCENE-6204, LUCENE-6208: Simplify CompoundFormat: remove files()

View File

@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.ToStringUtils;
@ -301,6 +302,16 @@ public class FilteredQuery extends Query {
* it returns a new {@code FilteredQuery} wrapping the rewritten query. */
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (filter instanceof QueryWrapperFilter) {
// In that case the filter does not implement random-access anyway so
// we want to take advantage of approximations
BooleanQuery rewritten = new BooleanQuery();
rewritten.add(query, Occur.MUST);
rewritten.add(((QueryWrapperFilter) filter).getQuery(), Occur.FILTER);
rewritten.setBoost(getBoost());
return rewritten;
}
final Query queryRewritten = query.rewrite(reader);
if (queryRewritten != query) {

View File

@ -17,12 +17,12 @@ package org.apache.lucene.search;
* limitations under the License.
*/
import org.apache.lucene.index.PostingsEnum;
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.util.Bits;
import java.io.IOException;
/**
* Constrains search results to only match those which also match a provided
* query.
@ -44,6 +44,13 @@ public class QueryWrapperFilter extends Filter {
this.query = query;
}
@Override
public Query rewrite(IndexReader reader) throws IOException {
ConstantScoreQuery rewritten = new ConstantScoreQuery(query);
rewritten.setBoost(0);
return rewritten;
}
/** returns the inner Query */
public final Query getQuery() {
return query;

View File

@ -25,6 +25,8 @@ import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.PostingsEnum;
@ -587,6 +589,51 @@ public class TestFilteredQuery extends LuceneTestCase {
assertEquals(totalDocsWithZero, search.totalHits);
IOUtils.close(reader, directory);
}
public void testPreservesScores() throws IOException {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
Document doc = new Document();
doc.add(new StringField("foo", "bar", Store.NO));
writer.addDocument(doc);
writer.commit();
final IndexReader reader = writer.getReader();
writer.close();
final IndexSearcher searcher = new IndexSearcher(reader);
final Query query = new TermQuery(new Term("foo", "bar"));
query.setBoost(random().nextFloat());
FilteredQuery fq = new FilteredQuery(query, new Filter() {
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptDocs)
throws IOException {
return new DocIdSet() {
@Override
public long ramBytesUsed() {
return 0;
}
@Override
public DocIdSetIterator iterator() throws IOException {
return DocIdSetIterator.all(context.reader().maxDoc());
}
};
}
@Override
public String toString(String field) {
return "dummy";
}
});
assertEquals(searcher.search(query, 1).scoreDocs[0].score, searcher.search(fq, 1).scoreDocs[0].score, 0f);
fq.setBoost(random().nextFloat());
// QueryWrapperFilter has special rewrite rules
FilteredQuery fq2 = new FilteredQuery(query, new QueryWrapperFilter(new MatchAllDocsQuery()));
fq2.setBoost(fq.getBoost());
fq2.setBoost(42);
assertEquals(searcher.search(fq, 1).scoreDocs[0].score, searcher.search(fq2, 1).scoreDocs[0].score, 10e-5);
reader.close();
dir.close();
}
}

View File

@ -16,11 +16,14 @@ package org.apache.lucene.search;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
@ -148,4 +151,40 @@ public class TestQueryWrapperFilter extends LuceneTestCase {
reader.close();
dir.close();
}
public void testScore() throws IOException {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
Document doc = new Document();
doc.add(new StringField("foo", "bar", Store.NO));
writer.addDocument(doc);
writer.commit();
final IndexReader reader = writer.getReader();
writer.close();
final IndexSearcher searcher = new IndexSearcher(reader);
final Query query = new QueryWrapperFilter(new TermQuery(new Term("foo", "bar")));
final TopDocs topDocs = searcher.search(query, 1);
assertEquals(1, topDocs.totalHits);
assertEquals(0f, topDocs.scoreDocs[0].score, 0f);
reader.close();
dir.close();
}
public void testQueryWrapperFilterPropagatesApproximations() throws IOException {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
Document doc = new Document();
doc.add(new StringField("foo", "bar", Store.NO));
writer.addDocument(doc);
writer.commit();
final IndexReader reader = writer.getReader();
writer.close();
final IndexSearcher searcher = new IndexSearcher(reader);
final Query query = new QueryWrapperFilter(new RandomApproximationQuery(new TermQuery(new Term("foo", "bar")), random()));
final Weight weight = searcher.createNormalizedWeight(query, random().nextBoolean());
final Scorer scorer = weight.scorer(reader.leaves().get(0), null);
assertNotNull(scorer.asTwoPhaseIterator());
reader.close();
dir.close();
}
}

View File

@ -30,6 +30,7 @@ import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.CachingWrapperFilter;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.FilteredQuery;
import org.apache.lucene.search.IndexSearcher;
@ -119,7 +120,7 @@ public class TestBlockJoinValidation extends LuceneTestCase {
Query parentQueryWithRandomChild = createParentQuery();
ToChildBlockJoinQuery blockJoinQuery = new ToChildBlockJoinQuery(parentQueryWithRandomChild, parentsFilter);
Filter childFilter = new QueryWrapperFilter(new TermQuery(new Term("common_field", "1")));
Filter childFilter = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Term("common_field", "1"))));
thrown.expect(IllegalStateException.class);
thrown.expectMessage(ToChildBlockJoinQuery.ILLEGAL_ADVANCE_ON_PARENT);
indexSearcher.search(new FilteredQuery(blockJoinQuery, childFilter), 1);