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 org.apache.lucene.analysis.standard.StandardAnalyzer;
22 import org.apache.lucene.document.Document;
23 import org.apache.lucene.document.Field;
24 import org.apache.lucene.index.IndexWriter;
25 import org.apache.lucene.index.Term;
26 import org.apache.lucene.queryParser.QueryParser;
27 import org.apache.lucene.search.spans.SpanNearQuery;
28 import org.apache.lucene.search.spans.SpanQuery;
29 import org.apache.lucene.search.spans.SpanTermQuery;
30 import org.apache.lucene.store.Directory;
34 * TestExplanations subclass focusing on basic query types
36 public class TestSimpleExplanations extends TestExplanations {
38 // we focus on queries that don't rewrite to other queries.
39 // if we get those covered well, then the ones that rewrite should
43 /* simple term tests */
45 public void testT1() throws Exception {
46 qtest("w1", new int[] { 0,1,2,3 });
48 public void testT2() throws Exception {
49 qtest("w1^1000", new int[] { 0,1,2,3 });
54 public void testMA1() throws Exception {
55 qtest(new MatchAllDocsQuery(), new int[] { 0,1,2,3 });
57 public void testMA2() throws Exception {
58 Query q=new MatchAllDocsQuery();
60 qtest(q, new int[] { 0,1,2,3 });
63 /* some simple phrase tests */
65 public void testP1() throws Exception {
66 qtest("\"w1 w2\"", new int[] { 0 });
68 public void testP2() throws Exception {
69 qtest("\"w1 w3\"", new int[] { 1,3 });
71 public void testP3() throws Exception {
72 qtest("\"w1 w2\"~1", new int[] { 0,1,2 });
74 public void testP4() throws Exception {
75 qtest("\"w2 w3\"~1", new int[] { 0,1,2,3 });
77 public void testP5() throws Exception {
78 qtest("\"w3 w2\"~1", new int[] { 1,3 });
80 public void testP6() throws Exception {
81 qtest("\"w3 w2\"~2", new int[] { 0,1,3 });
83 public void testP7() throws Exception {
84 qtest("\"w3 w2\"~3", new int[] { 0,1,2,3 });
87 /* some simple filtered query tests */
89 public void testFQ1() throws Exception {
90 qtest(new FilteredQuery(qp.parse("w1"),
91 new ItemizedFilter(new int[] {0,1,2,3})),
94 public void testFQ2() throws Exception {
95 qtest(new FilteredQuery(qp.parse("w1"),
96 new ItemizedFilter(new int[] {0,2,3})),
99 public void testFQ3() throws Exception {
100 qtest(new FilteredQuery(qp.parse("xx"),
101 new ItemizedFilter(new int[] {1,3})),
104 public void testFQ4() throws Exception {
105 qtest(new FilteredQuery(qp.parse("xx^1000"),
106 new ItemizedFilter(new int[] {1,3})),
109 public void testFQ6() throws Exception {
110 Query q = new FilteredQuery(qp.parse("xx"),
111 new ItemizedFilter(new int[] {1,3}));
113 qtest(q, new int[] {3});
116 /* ConstantScoreQueries */
118 public void testCSQ1() throws Exception {
119 Query q = new ConstantScoreQuery(new ItemizedFilter(new int[] {0,1,2,3}));
120 qtest(q, new int[] {0,1,2,3});
122 public void testCSQ2() throws Exception {
123 Query q = new ConstantScoreQuery(new ItemizedFilter(new int[] {1,3}));
124 qtest(q, new int[] {1,3});
126 public void testCSQ3() throws Exception {
127 Query q = new ConstantScoreQuery(new ItemizedFilter(new int[] {0,2}));
129 qtest(q, new int[] {0,2});
132 /* DisjunctionMaxQuery */
134 public void testDMQ1() throws Exception {
135 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f);
136 q.add(qp.parse("w1"));
137 q.add(qp.parse("w5"));
138 qtest(q, new int[] { 0,1,2,3 });
140 public void testDMQ2() throws Exception {
141 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
142 q.add(qp.parse("w1"));
143 q.add(qp.parse("w5"));
144 qtest(q, new int[] { 0,1,2,3 });
146 public void testDMQ3() throws Exception {
147 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
148 q.add(qp.parse("QQ"));
149 q.add(qp.parse("w5"));
150 qtest(q, new int[] { 0 });
152 public void testDMQ4() throws Exception {
153 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
154 q.add(qp.parse("QQ"));
155 q.add(qp.parse("xx"));
156 qtest(q, new int[] { 2,3 });
158 public void testDMQ5() throws Exception {
159 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
160 q.add(qp.parse("yy -QQ"));
161 q.add(qp.parse("xx"));
162 qtest(q, new int[] { 2,3 });
164 public void testDMQ6() throws Exception {
165 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
166 q.add(qp.parse("-yy w3"));
167 q.add(qp.parse("xx"));
168 qtest(q, new int[] { 0,1,2,3 });
170 public void testDMQ7() throws Exception {
171 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
172 q.add(qp.parse("-yy w3"));
173 q.add(qp.parse("w2"));
174 qtest(q, new int[] { 0,1,2,3 });
176 public void testDMQ8() throws Exception {
177 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
178 q.add(qp.parse("yy w5^100"));
179 q.add(qp.parse("xx^100000"));
180 qtest(q, new int[] { 0,2,3 });
182 public void testDMQ9() throws Exception {
183 DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
184 q.add(qp.parse("yy w5^100"));
185 q.add(qp.parse("xx^0"));
186 qtest(q, new int[] { 0,2,3 });
189 /* MultiPhraseQuery */
191 public void testMPQ1() throws Exception {
192 MultiPhraseQuery q = new MultiPhraseQuery();
193 q.add(ta(new String[] {"w1"}));
194 q.add(ta(new String[] {"w2","w3", "xx"}));
195 qtest(q, new int[] { 0,1,2,3 });
197 public void testMPQ2() throws Exception {
198 MultiPhraseQuery q = new MultiPhraseQuery();
199 q.add(ta(new String[] {"w1"}));
200 q.add(ta(new String[] {"w2","w3"}));
201 qtest(q, new int[] { 0,1,3 });
203 public void testMPQ3() throws Exception {
204 MultiPhraseQuery q = new MultiPhraseQuery();
205 q.add(ta(new String[] {"w1","xx"}));
206 q.add(ta(new String[] {"w2","w3"}));
207 qtest(q, new int[] { 0,1,2,3 });
209 public void testMPQ4() throws Exception {
210 MultiPhraseQuery q = new MultiPhraseQuery();
211 q.add(ta(new String[] {"w1"}));
212 q.add(ta(new String[] {"w2"}));
213 qtest(q, new int[] { 0 });
215 public void testMPQ5() throws Exception {
216 MultiPhraseQuery q = new MultiPhraseQuery();
217 q.add(ta(new String[] {"w1"}));
218 q.add(ta(new String[] {"w2"}));
220 qtest(q, new int[] { 0,1,2 });
222 public void testMPQ6() throws Exception {
223 MultiPhraseQuery q = new MultiPhraseQuery();
224 q.add(ta(new String[] {"w1","w3"}));
225 q.add(ta(new String[] {"w2"}));
227 qtest(q, new int[] { 0,1,2,3 });
230 /* some simple tests of boolean queries containing term queries */
232 public void testBQ1() throws Exception {
233 qtest("+w1 +w2", new int[] { 0,1,2,3 });
235 public void testBQ2() throws Exception {
236 qtest("+yy +w3", new int[] { 2,3 });
238 public void testBQ3() throws Exception {
239 qtest("yy +w3", new int[] { 0,1,2,3 });
241 public void testBQ4() throws Exception {
242 qtest("w1 (-xx w2)", new int[] { 0,1,2,3 });
244 public void testBQ5() throws Exception {
245 qtest("w1 (+qq w2)", new int[] { 0,1,2,3 });
247 public void testBQ6() throws Exception {
248 qtest("w1 -(-qq w5)", new int[] { 1,2,3 });
250 public void testBQ7() throws Exception {
251 qtest("+w1 +(qq (xx -w2) (+w3 +w4))", new int[] { 0 });
253 public void testBQ8() throws Exception {
254 qtest("+w1 (qq (xx -w2) (+w3 +w4))", new int[] { 0,1,2,3 });
256 public void testBQ9() throws Exception {
257 qtest("+w1 (qq (-xx w2) -(+w3 +w4))", new int[] { 0,1,2,3 });
259 public void testBQ10() throws Exception {
260 qtest("+w1 +(qq (-xx w2) -(+w3 +w4))", new int[] { 1 });
262 public void testBQ11() throws Exception {
263 qtest("w1 w2^1000.0", new int[] { 0,1,2,3 });
265 public void testBQ14() throws Exception {
266 BooleanQuery q = new BooleanQuery(true);
267 q.add(qp.parse("QQQQQ"), BooleanClause.Occur.SHOULD);
268 q.add(qp.parse("w1"), BooleanClause.Occur.SHOULD);
269 qtest(q, new int[] { 0,1,2,3 });
271 public void testBQ15() throws Exception {
272 BooleanQuery q = new BooleanQuery(true);
273 q.add(qp.parse("QQQQQ"), BooleanClause.Occur.MUST_NOT);
274 q.add(qp.parse("w1"), BooleanClause.Occur.SHOULD);
275 qtest(q, new int[] { 0,1,2,3 });
277 public void testBQ16() throws Exception {
278 BooleanQuery q = new BooleanQuery(true);
279 q.add(qp.parse("QQQQQ"), BooleanClause.Occur.SHOULD);
280 q.add(qp.parse("w1 -xx"), BooleanClause.Occur.SHOULD);
281 qtest(q, new int[] { 0,1 });
283 public void testBQ17() throws Exception {
284 BooleanQuery q = new BooleanQuery(true);
285 q.add(qp.parse("w2"), BooleanClause.Occur.SHOULD);
286 q.add(qp.parse("w1 -xx"), BooleanClause.Occur.SHOULD);
287 qtest(q, new int[] { 0,1,2,3 });
289 public void testBQ19() throws Exception {
290 qtest("-yy w3", new int[] { 0,1 });
293 public void testBQ20() throws Exception {
294 BooleanQuery q = new BooleanQuery();
295 q.setMinimumNumberShouldMatch(2);
296 q.add(qp.parse("QQQQQ"), BooleanClause.Occur.SHOULD);
297 q.add(qp.parse("yy"), BooleanClause.Occur.SHOULD);
298 q.add(qp.parse("zz"), BooleanClause.Occur.SHOULD);
299 q.add(qp.parse("w5"), BooleanClause.Occur.SHOULD);
300 q.add(qp.parse("w4"), BooleanClause.Occur.SHOULD);
302 qtest(q, new int[] { 0,3 });
306 public void testTermQueryMultiSearcherExplain() throws Exception {
307 // creating two directories for indices
308 Directory indexStoreA = newDirectory();
309 Directory indexStoreB = newDirectory();
311 Document lDoc = new Document();
312 lDoc.add(newField("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));
313 Document lDoc2 = new Document();
314 lDoc2.add(newField("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));
315 Document lDoc3 = new Document();
316 lDoc3.add(newField("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));
318 IndexWriter writerA = new IndexWriter(indexStoreA, newIndexWriterConfig(
319 TEST_VERSION_CURRENT, new StandardAnalyzer(
320 TEST_VERSION_CURRENT)));
321 IndexWriter writerB = new IndexWriter(indexStoreB, newIndexWriterConfig(
322 TEST_VERSION_CURRENT, new StandardAnalyzer(
323 TEST_VERSION_CURRENT)));
325 writerA.addDocument(lDoc);
326 writerA.addDocument(lDoc2);
330 writerB.addDocument(lDoc3);
333 QueryParser parser = new QueryParser(TEST_VERSION_CURRENT, "fulltext", new StandardAnalyzer(TEST_VERSION_CURRENT));
334 Query query = parser.parse("handle:1");
336 Searcher[] searchers = new Searcher[2];
337 searchers[0] = new IndexSearcher(indexStoreB, true);
338 searchers[1] = new IndexSearcher(indexStoreA, true);
339 Searcher mSearcher = new MultiSearcher(searchers);
340 ScoreDoc[] hits = mSearcher.search(query, null, 1000).scoreDocs;
342 assertEquals(3, hits.length);
344 Explanation explain = mSearcher.explain(query, hits[0].doc);
345 String exp = explain.toString(0);
346 assertTrue(exp, exp.indexOf("maxDocs=3") > -1);
347 assertTrue(exp, exp.indexOf("docFreq=3") > -1);
349 query = parser.parse("handle:\"1 2\"");
350 hits = mSearcher.search(query, null, 1000).scoreDocs;
352 assertEquals(3, hits.length);
354 explain = mSearcher.explain(query, hits[0].doc);
355 exp = explain.toString(0);
356 assertTrue(exp, exp.indexOf("1=3") > -1);
357 assertTrue(exp, exp.indexOf("2=3") > -1);
359 query = new SpanNearQuery(new SpanQuery[] {
360 new SpanTermQuery(new Term("handle", "1")),
361 new SpanTermQuery(new Term("handle", "2")) }, 0, true);
362 hits = mSearcher.search(query, null, 1000).scoreDocs;
364 assertEquals(3, hits.length);
366 explain = mSearcher.explain(query, hits[0].doc);
367 exp = explain.toString(0);
368 assertTrue(exp, exp.indexOf("1=3") > -1);
369 assertTrue(exp, exp.indexOf("2=3") > -1);
375 /* BQ of TQ: using alt so some fields have zero boost and some don't */
377 public void testMultiFieldBQ1() throws Exception {
378 qtest("+w1 +alt:w2", new int[] { 0,1,2,3 });
380 public void testMultiFieldBQ2() throws Exception {
381 qtest("+yy +alt:w3", new int[] { 2,3 });
383 public void testMultiFieldBQ3() throws Exception {
384 qtest("yy +alt:w3", new int[] { 0,1,2,3 });
386 public void testMultiFieldBQ4() throws Exception {
387 qtest("w1 (-xx alt:w2)", new int[] { 0,1,2,3 });
389 public void testMultiFieldBQ5() throws Exception {
390 qtest("w1 (+alt:qq alt:w2)", new int[] { 0,1,2,3 });
392 public void testMultiFieldBQ6() throws Exception {
393 qtest("w1 -(-alt:qq alt:w5)", new int[] { 1,2,3 });
395 public void testMultiFieldBQ7() throws Exception {
396 qtest("+w1 +(alt:qq (alt:xx -alt:w2) (+alt:w3 +alt:w4))", new int[] { 0 });
398 public void testMultiFieldBQ8() throws Exception {
399 qtest("+alt:w1 (qq (alt:xx -w2) (+alt:w3 +w4))", new int[] { 0,1,2,3 });
401 public void testMultiFieldBQ9() throws Exception {
402 qtest("+w1 (alt:qq (-xx w2) -(+alt:w3 +w4))", new int[] { 0,1,2,3 });
404 public void testMultiFieldBQ10() throws Exception {
405 qtest("+w1 +(alt:qq (-xx alt:w2) -(+alt:w3 +w4))", new int[] { 1 });
408 /* BQ of PQ: using alt so some fields have zero boost and some don't */
410 public void testMultiFieldBQofPQ1() throws Exception {
411 qtest("\"w1 w2\" alt:\"w1 w2\"", new int[] { 0 });
413 public void testMultiFieldBQofPQ2() throws Exception {
414 qtest("\"w1 w3\" alt:\"w1 w3\"", new int[] { 1,3 });
416 public void testMultiFieldBQofPQ3() throws Exception {
417 qtest("\"w1 w2\"~1 alt:\"w1 w2\"~1", new int[] { 0,1,2 });
419 public void testMultiFieldBQofPQ4() throws Exception {
420 qtest("\"w2 w3\"~1 alt:\"w2 w3\"~1", new int[] { 0,1,2,3 });
422 public void testMultiFieldBQofPQ5() throws Exception {
423 qtest("\"w3 w2\"~1 alt:\"w3 w2\"~1", new int[] { 1,3 });
425 public void testMultiFieldBQofPQ6() throws Exception {
426 qtest("\"w3 w2\"~2 alt:\"w3 w2\"~2", new int[] { 0,1,3 });
428 public void testMultiFieldBQofPQ7() throws Exception {
429 qtest("\"w3 w2\"~3 alt:\"w3 w2\"~3", new int[] { 0,1,2,3 });