001: package org.apache.lucene.search;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import org.apache.lucene.store.RAMDirectory;
021:
022: import org.apache.lucene.index.IndexWriter;
023: import org.apache.lucene.index.Term;
024:
025: import org.apache.lucene.analysis.WhitespaceAnalyzer;
026:
027: import org.apache.lucene.document.Document;
028: import org.apache.lucene.document.Field;
029:
030: import org.apache.lucene.queryParser.QueryParser;
031: import org.apache.lucene.queryParser.ParseException;
032:
033: import org.apache.lucene.util.LuceneTestCase;
034:
035: import java.util.Random;
036:
037: /** Test BooleanQuery2 against BooleanQuery by overriding the standard query parser.
038: * This also tests the scoring order of BooleanQuery.
039: */
040: public class TestBoolean2 extends LuceneTestCase {
041: private IndexSearcher searcher;
042:
043: public static final String field = "field";
044:
045: public void setUp() throws Exception {
046: super .setUp();
047: RAMDirectory directory = new RAMDirectory();
048: IndexWriter writer = new IndexWriter(directory,
049: new WhitespaceAnalyzer(), true);
050: for (int i = 0; i < docFields.length; i++) {
051: Document doc = new Document();
052: doc.add(new Field(field, docFields[i], Field.Store.NO,
053: Field.Index.TOKENIZED));
054: writer.addDocument(doc);
055: }
056: writer.close();
057: searcher = new IndexSearcher(directory);
058: }
059:
060: private String[] docFields = { "w1 w2 w3 w4 w5", "w1 w3 w2 w3",
061: "w1 xx w2 yy w3", "w1 w3 xx w2 yy w3" };
062:
063: public Query makeQuery(String queryText) throws ParseException {
064: Query q = (new QueryParser(field, new WhitespaceAnalyzer()))
065: .parse(queryText);
066: return q;
067: }
068:
069: public void queriesTest(String queryText, int[] expDocNrs)
070: throws Exception {
071: //System.out.println();
072: //System.out.println("Query: " + queryText);
073: try {
074: Query query1 = makeQuery(queryText);
075: BooleanQuery.setAllowDocsOutOfOrder(true);
076: Hits hits1 = searcher.search(query1);
077:
078: Query query2 = makeQuery(queryText); // there should be no need to parse again...
079: BooleanQuery.setAllowDocsOutOfOrder(false);
080: Hits hits2 = searcher.search(query2);
081:
082: CheckHits.checkHitsQuery(query2, hits1, hits2, expDocNrs);
083: } finally { // even when a test fails.
084: BooleanQuery.setAllowDocsOutOfOrder(false);
085: }
086: }
087:
088: public void testQueries01() throws Exception {
089: String queryText = "+w3 +xx";
090: int[] expDocNrs = { 2, 3 };
091: queriesTest(queryText, expDocNrs);
092: }
093:
094: public void testQueries02() throws Exception {
095: String queryText = "+w3 xx";
096: int[] expDocNrs = { 2, 3, 1, 0 };
097: queriesTest(queryText, expDocNrs);
098: }
099:
100: public void testQueries03() throws Exception {
101: String queryText = "w3 xx";
102: int[] expDocNrs = { 2, 3, 1, 0 };
103: queriesTest(queryText, expDocNrs);
104: }
105:
106: public void testQueries04() throws Exception {
107: String queryText = "w3 -xx";
108: int[] expDocNrs = { 1, 0 };
109: queriesTest(queryText, expDocNrs);
110: }
111:
112: public void testQueries05() throws Exception {
113: String queryText = "+w3 -xx";
114: int[] expDocNrs = { 1, 0 };
115: queriesTest(queryText, expDocNrs);
116: }
117:
118: public void testQueries06() throws Exception {
119: String queryText = "+w3 -xx -w5";
120: int[] expDocNrs = { 1 };
121: queriesTest(queryText, expDocNrs);
122: }
123:
124: public void testQueries07() throws Exception {
125: String queryText = "-w3 -xx -w5";
126: int[] expDocNrs = {};
127: queriesTest(queryText, expDocNrs);
128: }
129:
130: public void testQueries08() throws Exception {
131: String queryText = "+w3 xx -w5";
132: int[] expDocNrs = { 2, 3, 1 };
133: queriesTest(queryText, expDocNrs);
134: }
135:
136: public void testQueries09() throws Exception {
137: String queryText = "+w3 +xx +w2 zz";
138: int[] expDocNrs = { 2, 3 };
139: queriesTest(queryText, expDocNrs);
140: }
141:
142: public void testQueries10() throws Exception {
143: String queryText = "+w3 +xx +w2 zz";
144: int[] expDocNrs = { 2, 3 };
145: searcher.setSimilarity(new DefaultSimilarity() {
146: public float coord(int overlap, int maxOverlap) {
147: return overlap / ((float) maxOverlap - 1);
148: }
149: });
150: queriesTest(queryText, expDocNrs);
151: }
152:
153: public void testRandomQueries() throws Exception {
154: Random rnd = new Random(0);
155:
156: String[] vals = { "w1", "w2", "w3", "w4", "w5", "xx", "yy",
157: "zzz" };
158:
159: int tot = 0;
160:
161: try {
162:
163: // increase number of iterations for more complete testing
164: for (int i = 0; i < 1000; i++) {
165: int level = rnd.nextInt(3);
166: BooleanQuery q1 = randBoolQuery(new Random(i), level,
167: field, vals, null);
168:
169: // Can't sort by relevance since floating point numbers may not quite
170: // match up.
171: Sort sort = Sort.INDEXORDER;
172:
173: BooleanQuery.setAllowDocsOutOfOrder(false);
174:
175: QueryUtils.check(q1, searcher);
176:
177: Hits hits1 = searcher.search(q1, sort);
178: if (hits1.length() > 0)
179: hits1.id(hits1.length() - 1);
180:
181: BooleanQuery.setAllowDocsOutOfOrder(true);
182: Hits hits2 = searcher.search(q1, sort);
183: if (hits2.length() > 0)
184: hits2.id(hits1.length() - 1);
185: tot += hits2.length();
186: CheckHits.checkEqual(q1, hits1, hits2);
187: }
188:
189: } finally { // even when a test fails.
190: BooleanQuery.setAllowDocsOutOfOrder(false);
191: }
192:
193: // System.out.println("Total hits:"+tot);
194: }
195:
196: // used to set properties or change every BooleanQuery
197: // generated from randBoolQuery.
198: public static interface Callback {
199: public void postCreate(BooleanQuery q);
200: }
201:
202: // Random rnd is passed in so that the exact same random query may be created
203: // more than once.
204: public static BooleanQuery randBoolQuery(Random rnd, int level,
205: String field, String[] vals, Callback cb) {
206: BooleanQuery current = new BooleanQuery(rnd.nextInt() < 0);
207: for (int i = 0; i < rnd.nextInt(vals.length) + 1; i++) {
208: int qType = 0; // term query
209: if (level > 0) {
210: qType = rnd.nextInt(10);
211: }
212: Query q;
213: if (qType < 7)
214: q = new TermQuery(new Term(field, vals[rnd
215: .nextInt(vals.length)]));
216: else
217: q = randBoolQuery(rnd, level - 1, field, vals, cb);
218:
219: int r = rnd.nextInt(10);
220: BooleanClause.Occur occur;
221: if (r < 2)
222: occur = BooleanClause.Occur.MUST_NOT;
223: else if (r < 5)
224: occur = BooleanClause.Occur.MUST;
225: else
226: occur = BooleanClause.Occur.SHOULD;
227:
228: current.add(q, occur);
229: }
230: if (cb != null)
231: cb.postCreate(current);
232: return current;
233: }
234:
235: }
|