mirror of https://github.com/apache/lucene.git
new Query which applies a Filter to another Query
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@150308 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
96e1b41127
commit
30ef9989dc
|
@ -0,0 +1,121 @@
|
||||||
|
package org.apache.lucene.search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2004 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed 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.IndexReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A query that applies a filter to the results of another query.
|
||||||
|
*
|
||||||
|
* <p>Note: the bits are retrieved from the filter each time this
|
||||||
|
* query is used in a search - use a CachingWrapperFilter to avoid
|
||||||
|
* regenerating the bits every time.
|
||||||
|
*
|
||||||
|
* <p>Created: Apr 20, 2004 8:58:29 AM
|
||||||
|
*
|
||||||
|
* @author Tim Jones
|
||||||
|
* @since 1.4
|
||||||
|
* @version $Id$
|
||||||
|
* @see CachingWrapperFilter
|
||||||
|
*/
|
||||||
|
public class FilteredQuery
|
||||||
|
extends Query {
|
||||||
|
|
||||||
|
Query query;
|
||||||
|
Filter filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new query which applies a filter to the results of the original query.
|
||||||
|
* Filter.bits() will be called every time this query is used in a search.
|
||||||
|
* @param query Query to be filtered, cannot be <code>null</code>.
|
||||||
|
* @param filter Filter to apply to query results, cannot be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public FilteredQuery (Query query, Filter filter) {
|
||||||
|
this.query = query;
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Weight that applies the filter to the enclosed query's Weight.
|
||||||
|
* This is accomplished by overriding the Scorer returned by the Weight.
|
||||||
|
*/
|
||||||
|
protected Weight createWeight (final Searcher searcher) {
|
||||||
|
final Weight weight = query.createWeight (searcher);
|
||||||
|
return new Weight() {
|
||||||
|
|
||||||
|
// pass these methods through to enclosed query's weight
|
||||||
|
public float getValue() { return weight.getValue(); }
|
||||||
|
public float sumOfSquaredWeights() throws IOException { return weight.sumOfSquaredWeights(); }
|
||||||
|
public void normalize (float v) { weight.normalize(v); }
|
||||||
|
public Explanation explain (IndexReader ir, int i) throws IOException { return weight.explain (ir, i); }
|
||||||
|
|
||||||
|
// return this query
|
||||||
|
public Query getQuery() { return FilteredQuery.this; }
|
||||||
|
|
||||||
|
// return a scorer that overrides the enclosed query's score if
|
||||||
|
// the given hit has been filtered out.
|
||||||
|
public Scorer scorer (IndexReader indexReader) throws IOException {
|
||||||
|
final Scorer scorer = weight.scorer (indexReader);
|
||||||
|
final BitSet bitset = filter.bits (indexReader);
|
||||||
|
return new Scorer (query.getSimilarity (searcher)) {
|
||||||
|
|
||||||
|
// pass these methods through to the enclosed scorer
|
||||||
|
public boolean next() throws IOException { return scorer.next(); }
|
||||||
|
public int doc() { return scorer.doc(); }
|
||||||
|
public boolean skipTo (int i) throws IOException { return scorer.skipTo(i); }
|
||||||
|
|
||||||
|
// if the document has been filtered out, set score to 0.0
|
||||||
|
public float score() throws IOException {
|
||||||
|
return (bitset.get(scorer.doc())) ? scorer.score() : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add an explanation about whether the document was filtered
|
||||||
|
public Explanation explain (int i) throws IOException {
|
||||||
|
Explanation exp = scorer.explain (i);
|
||||||
|
if (bitset.get(i))
|
||||||
|
exp.setDescription ("allowed by filter: "+exp.getDescription());
|
||||||
|
else
|
||||||
|
exp.setDescription ("removed by filter: "+exp.getDescription());
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Prints a user-readable version of this query. */
|
||||||
|
public String toString (String s) {
|
||||||
|
return "filtered("+query.toString()+")";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true iff <code>o</code> is equal to this. */
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof FilteredQuery) {
|
||||||
|
FilteredQuery fq = (FilteredQuery) o;
|
||||||
|
return (query.equals(fq.query) && filter.equals(fq.filter));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a hash code value for this object. */
|
||||||
|
public int hashCode() {
|
||||||
|
return query.hashCode() ^ filter.hashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package org.apache.lucene.search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2004 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed 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 junit.framework.TestCase;
|
||||||
|
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.document.Field;
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
import org.apache.lucene.index.Term;
|
||||||
|
import org.apache.lucene.store.RAMDirectory;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FilteredQuery JUnit tests.
|
||||||
|
*
|
||||||
|
* <p>Created: Apr 21, 2004 1:21:46 PM
|
||||||
|
*
|
||||||
|
* @author Tim Jones
|
||||||
|
* @version $Id$
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public class TestFilteredQuery
|
||||||
|
extends TestCase {
|
||||||
|
|
||||||
|
private IndexSearcher searcher;
|
||||||
|
private RAMDirectory directory;
|
||||||
|
private Query query;
|
||||||
|
private Filter filter;
|
||||||
|
|
||||||
|
public void setUp()
|
||||||
|
throws Exception {
|
||||||
|
directory = new RAMDirectory();
|
||||||
|
IndexWriter writer = new IndexWriter (directory, new WhitespaceAnalyzer(), true);
|
||||||
|
|
||||||
|
Document doc = new Document();
|
||||||
|
doc.add (Field.Text ("field", "one two three four five"));
|
||||||
|
doc.add (Field.Text ("sorter", "b"));
|
||||||
|
writer.addDocument (doc);
|
||||||
|
|
||||||
|
doc = new Document();
|
||||||
|
doc.add (Field.Text ("field", "one two three four"));
|
||||||
|
doc.add (Field.Text ("sorter", "d"));
|
||||||
|
writer.addDocument (doc);
|
||||||
|
|
||||||
|
doc = new Document();
|
||||||
|
doc.add (Field.Text ("field", "one two three y"));
|
||||||
|
doc.add (Field.Text ("sorter", "a"));
|
||||||
|
writer.addDocument (doc);
|
||||||
|
|
||||||
|
doc = new Document();
|
||||||
|
doc.add (Field.Text ("field", "one two x"));
|
||||||
|
doc.add (Field.Text ("sorter", "c"));
|
||||||
|
writer.addDocument (doc);
|
||||||
|
|
||||||
|
writer.optimize ();
|
||||||
|
writer.close ();
|
||||||
|
|
||||||
|
searcher = new IndexSearcher (directory);
|
||||||
|
query = new TermQuery (new Term ("field", "three"));
|
||||||
|
filter = new Filter() {
|
||||||
|
public BitSet bits (IndexReader reader) throws IOException {
|
||||||
|
BitSet bitset = new BitSet(5);
|
||||||
|
bitset.set (1);
|
||||||
|
bitset.set (3);
|
||||||
|
return bitset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown()
|
||||||
|
throws Exception {
|
||||||
|
searcher.close();
|
||||||
|
directory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFilteredQuery()
|
||||||
|
throws Exception {
|
||||||
|
Query filteredquery = new FilteredQuery (query, filter);
|
||||||
|
Hits hits = searcher.search (filteredquery);
|
||||||
|
assertEquals (hits.length(), 1);
|
||||||
|
assertEquals (hits.id(0), 1);
|
||||||
|
|
||||||
|
hits = searcher.search (filteredquery, new Sort("sorter"));
|
||||||
|
assertEquals (hits.length(), 1);
|
||||||
|
assertEquals (hits.id(0), 1);
|
||||||
|
|
||||||
|
filteredquery = new FilteredQuery (new TermQuery (new Term ("field", "one")), filter);
|
||||||
|
hits = searcher.search (filteredquery);
|
||||||
|
assertEquals (hits.length(), 2);
|
||||||
|
|
||||||
|
filteredquery = new FilteredQuery (new TermQuery (new Term ("field", "x")), filter);
|
||||||
|
hits = searcher.search (filteredquery);
|
||||||
|
assertEquals (hits.length(), 1);
|
||||||
|
assertEquals (hits.id(0), 3);
|
||||||
|
|
||||||
|
filteredquery = new FilteredQuery (new TermQuery (new Term ("field", "y")), filter);
|
||||||
|
hits = searcher.search (filteredquery);
|
||||||
|
assertEquals (hits.length(), 0);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue