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);
327
writerA.forceMerge(1);
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 });