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