1 package org.apache.lucene.search;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import java.io.IOException;
22 import org.apache.lucene.analysis.MockAnalyzer;
23 import org.apache.lucene.analysis.MockTokenizer;
24 import org.apache.lucene.document.Document;
25 import org.apache.lucene.document.Field;
26 import org.apache.lucene.index.IndexReader;
27 import org.apache.lucene.index.RandomIndexWriter;
28 import org.apache.lucene.index.Term;
29 import org.apache.lucene.search.BooleanClause.Occur;
30 import org.apache.lucene.store.Directory;
31 import org.apache.lucene.util.LuceneTestCase;
33 public class BooleanFilterTest extends LuceneTestCase {
34 private Directory directory;
35 private IndexReader reader;
38 public void setUp() throws Exception {
40 directory = newDirectory();
41 RandomIndexWriter writer = new RandomIndexWriter(random, directory, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false));
43 //Add series of docs with filterable fields : acces rights, prices, dates and "in-stock" flags
44 addDoc(writer, "admin guest", "010", "20040101","Y");
45 addDoc(writer, "guest", "020", "20040101","Y");
46 addDoc(writer, "guest", "020", "20050101","Y");
47 addDoc(writer, "admin", "020", "20050101","Maybe");
48 addDoc(writer, "admin guest", "030", "20050101","N");
49 reader = writer.getReader();
54 public void tearDown() throws Exception {
60 private void addDoc(RandomIndexWriter writer, String accessRights, String price, String date, String inStock) throws IOException
62 Document doc=new Document();
63 doc.add(newField("accessRights",accessRights,Field.Store.YES,Field.Index.ANALYZED));
64 doc.add(newField("price",price,Field.Store.YES,Field.Index.ANALYZED));
65 doc.add(newField("date",date,Field.Store.YES,Field.Index.ANALYZED));
66 doc.add(newField("inStock",inStock,Field.Store.YES,Field.Index.ANALYZED));
67 writer.addDocument(doc);
70 private Filter getRangeFilter(String field,String lowerPrice, String upperPrice)
72 Filter f = new TermRangeFilter(field,lowerPrice,upperPrice,true,true);
76 private Filter getTermsFilter(String field, String text) {
77 TermsFilter tf = new TermsFilter();
78 tf.addTerm(new Term(field, text));
83 private Filter getWrappedTermQuery(String field, String text) {
84 return new QueryWrapperFilter(new TermQuery(new Term(field, text)));
87 private Filter getNullDISFilter() {
90 public DocIdSet getDocIdSet(IndexReader context) {
96 private Filter getNullDISIFilter() {
99 public DocIdSet getDocIdSet(IndexReader context) {
100 return new DocIdSet() {
102 public DocIdSetIterator iterator() {
107 public boolean isCacheable() {
115 private void tstFilterCard(String mes, int expected, Filter filt)
117 // BooleanFilter never returns null DIS or null DISI!
118 DocIdSetIterator disi = filt.getDocIdSet(reader).iterator();
120 while (disi.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
123 assertEquals(mes, expected, actual);
127 public void testShould() throws Exception {
128 BooleanFilter booleanFilter = new BooleanFilter();
129 booleanFilter.add(getTermsFilter("price", "030"), Occur.SHOULD);
130 tstFilterCard("Should retrieves only 1 doc", 1, booleanFilter);
132 // same with a real DISI (no OpenBitSetIterator)
133 booleanFilter = new BooleanFilter();
134 booleanFilter.add(getWrappedTermQuery("price", "030"), Occur.SHOULD);
135 tstFilterCard("Should retrieves only 1 doc", 1, booleanFilter);
138 public void testShoulds() throws Exception {
139 BooleanFilter booleanFilter = new BooleanFilter();
140 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
141 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
142 tstFilterCard("Shoulds are Ored together", 5, booleanFilter);
145 public void testShouldsAndMustNot() throws Exception {
146 BooleanFilter booleanFilter = new BooleanFilter();
147 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
148 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
149 booleanFilter.add(getTermsFilter("inStock", "N"), Occur.MUST_NOT);
150 tstFilterCard("Shoulds Ored but AndNot", 4, booleanFilter);
152 booleanFilter.add(getTermsFilter("inStock", "Maybe"), Occur.MUST_NOT);
153 tstFilterCard("Shoulds Ored but AndNots", 3, booleanFilter);
155 // same with a real DISI (no OpenBitSetIterator)
156 booleanFilter = new BooleanFilter();
157 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
158 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
159 booleanFilter.add(getWrappedTermQuery("inStock", "N"), Occur.MUST_NOT);
160 tstFilterCard("Shoulds Ored but AndNot", 4, booleanFilter);
162 booleanFilter.add(getWrappedTermQuery("inStock", "Maybe"), Occur.MUST_NOT);
163 tstFilterCard("Shoulds Ored but AndNots", 3, booleanFilter);
166 public void testShouldsAndMust() throws Exception {
167 BooleanFilter booleanFilter = new BooleanFilter();
168 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
169 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
170 booleanFilter.add(getTermsFilter("accessRights", "admin"), Occur.MUST);
171 tstFilterCard("Shoulds Ored but MUST", 3, booleanFilter);
173 // same with a real DISI (no OpenBitSetIterator)
174 booleanFilter = new BooleanFilter();
175 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
176 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
177 booleanFilter.add(getWrappedTermQuery("accessRights", "admin"), Occur.MUST);
178 tstFilterCard("Shoulds Ored but MUST", 3, booleanFilter);
181 public void testShouldsAndMusts() throws Exception {
182 BooleanFilter booleanFilter = new BooleanFilter();
183 booleanFilter.add(getRangeFilter("price", "010", "020"), Occur.SHOULD);
184 booleanFilter.add(getRangeFilter("price", "020", "030"), Occur.SHOULD);
185 booleanFilter.add(getTermsFilter("accessRights", "admin"), Occur.MUST);
186 booleanFilter.add(getRangeFilter("date", "20040101", "20041231"), Occur.MUST);
187 tstFilterCard("Shoulds Ored but MUSTs ANDED", 1, booleanFilter);
190 public void testShouldsAndMustsAndMustNot() throws Exception {
191 BooleanFilter booleanFilter = new BooleanFilter();
192 booleanFilter.add(getRangeFilter("price", "030", "040"), Occur.SHOULD);
193 booleanFilter.add(getTermsFilter("accessRights", "admin"), Occur.MUST);
194 booleanFilter.add(getRangeFilter("date", "20050101", "20051231"), Occur.MUST);
195 booleanFilter.add(getTermsFilter("inStock", "N"), Occur.MUST_NOT);
196 tstFilterCard("Shoulds Ored but MUSTs ANDED and MustNot", 0, booleanFilter);
198 // same with a real DISI (no OpenBitSetIterator)
199 booleanFilter = new BooleanFilter();
200 booleanFilter.add(getRangeFilter("price", "030", "040"), Occur.SHOULD);
201 booleanFilter.add(getWrappedTermQuery("accessRights", "admin"), Occur.MUST);
202 booleanFilter.add(getRangeFilter("date", "20050101", "20051231"), Occur.MUST);
203 booleanFilter.add(getWrappedTermQuery("inStock", "N"), Occur.MUST_NOT);
204 tstFilterCard("Shoulds Ored but MUSTs ANDED and MustNot", 0, booleanFilter);
207 public void testJustMust() throws Exception {
208 BooleanFilter booleanFilter = new BooleanFilter();
209 booleanFilter.add(getTermsFilter("accessRights", "admin"), Occur.MUST);
210 tstFilterCard("MUST", 3, booleanFilter);
212 // same with a real DISI (no OpenBitSetIterator)
213 booleanFilter = new BooleanFilter();
214 booleanFilter.add(getWrappedTermQuery("accessRights", "admin"), Occur.MUST);
215 tstFilterCard("MUST", 3, booleanFilter);
218 public void testJustMustNot() throws Exception {
219 BooleanFilter booleanFilter = new BooleanFilter();
220 booleanFilter.add(getTermsFilter("inStock", "N"), Occur.MUST_NOT);
221 tstFilterCard("MUST_NOT", 4, booleanFilter);
223 // same with a real DISI (no OpenBitSetIterator)
224 booleanFilter = new BooleanFilter();
225 booleanFilter.add(getWrappedTermQuery("inStock", "N"), Occur.MUST_NOT);
226 tstFilterCard("MUST_NOT", 4, booleanFilter);
229 public void testMustAndMustNot() throws Exception {
230 BooleanFilter booleanFilter = new BooleanFilter();
231 booleanFilter.add(getTermsFilter("inStock", "N"), Occur.MUST);
232 booleanFilter.add(getTermsFilter("price", "030"), Occur.MUST_NOT);
233 tstFilterCard("MUST_NOT wins over MUST for same docs", 0, booleanFilter);
235 // same with a real DISI (no OpenBitSetIterator)
236 booleanFilter = new BooleanFilter();
237 booleanFilter.add(getWrappedTermQuery("inStock", "N"), Occur.MUST);
238 booleanFilter.add(getWrappedTermQuery("price", "030"), Occur.MUST_NOT);
239 tstFilterCard("MUST_NOT wins over MUST for same docs", 0, booleanFilter);
242 public void testEmpty() throws Exception {
243 BooleanFilter booleanFilter = new BooleanFilter();
244 tstFilterCard("empty BooleanFilter returns no results", 0, booleanFilter);
247 public void testCombinedNullDocIdSets() throws Exception {
248 BooleanFilter booleanFilter = new BooleanFilter();
249 booleanFilter.add(getTermsFilter("price", "030"), Occur.MUST);
250 booleanFilter.add(getNullDISFilter(), Occur.MUST);
251 tstFilterCard("A MUST filter that returns a null DIS should never return documents", 0, booleanFilter);
253 booleanFilter = new BooleanFilter();
254 booleanFilter.add(getTermsFilter("price", "030"), Occur.MUST);
255 booleanFilter.add(getNullDISIFilter(), Occur.MUST);
256 tstFilterCard("A MUST filter that returns a null DISI should never return documents", 0, booleanFilter);
258 booleanFilter = new BooleanFilter();
259 booleanFilter.add(getTermsFilter("price", "030"), Occur.SHOULD);
260 booleanFilter.add(getNullDISFilter(), Occur.SHOULD);
261 tstFilterCard("A SHOULD filter that returns a null DIS should be invisible", 1, booleanFilter);
263 booleanFilter = new BooleanFilter();
264 booleanFilter.add(getTermsFilter("price", "030"), Occur.SHOULD);
265 booleanFilter.add(getNullDISIFilter(), Occur.SHOULD);
266 tstFilterCard("A SHOULD filter that returns a null DISI should be invisible", 1, booleanFilter);
268 booleanFilter = new BooleanFilter();
269 booleanFilter.add(getTermsFilter("price", "030"), Occur.MUST);
270 booleanFilter.add(getNullDISFilter(), Occur.MUST_NOT);
271 tstFilterCard("A MUST_NOT filter that returns a null DIS should be invisible", 1, booleanFilter);
273 booleanFilter = new BooleanFilter();
274 booleanFilter.add(getTermsFilter("price", "030"), Occur.MUST);
275 booleanFilter.add(getNullDISIFilter(), Occur.MUST_NOT);
276 tstFilterCard("A MUST_NOT filter that returns a null DISI should be invisible", 1, booleanFilter);
279 public void testJustNullDocIdSets() throws Exception {
280 BooleanFilter booleanFilter = new BooleanFilter();
281 booleanFilter.add(getNullDISFilter(), Occur.MUST);
282 tstFilterCard("A MUST filter that returns a null DIS should never return documents", 0, booleanFilter);
284 booleanFilter = new BooleanFilter();
285 booleanFilter.add(getNullDISIFilter(), Occur.MUST);
286 tstFilterCard("A MUST filter that returns a null DISI should never return documents", 0, booleanFilter);
288 booleanFilter = new BooleanFilter();
289 booleanFilter.add(getNullDISFilter(), Occur.SHOULD);
290 tstFilterCard("A single SHOULD filter that returns a null DIS should never return documents", 0, booleanFilter);
292 booleanFilter = new BooleanFilter();
293 booleanFilter.add(getNullDISIFilter(), Occur.SHOULD);
294 tstFilterCard("A single SHOULD filter that returns a null DISI should never return documents", 0, booleanFilter);
296 booleanFilter = new BooleanFilter();
297 booleanFilter.add(getNullDISFilter(), Occur.MUST_NOT);
298 tstFilterCard("A single MUST_NOT filter that returns a null DIS should be invisible", 5, booleanFilter);
300 booleanFilter = new BooleanFilter();
301 booleanFilter.add(getNullDISIFilter(), Occur.MUST_NOT);
302 tstFilterCard("A single MUST_NOT filter that returns a null DIS should be invisible", 5, booleanFilter);