~ubuntu-branches/ubuntu/trusty/pylucene/trusty

« back to all changes in this revision

Viewing changes to lucene-java-3.5.0/lucene/backwards/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java

  • Committer: Package Import Robot
  • Author(s): Dmitry Nezhevenko
  • Date: 2012-04-23 16:43:55 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120423164355-grqtepnwtecdjfk2
Tags: 3.5.0-1
* New maintainer (closes: 670179)
* New upstream release
* Switch to dpkg-source 3.0 (quilt) format
* Switch to machine-readable debian/copyright
* Bump debian/compat to 8, drop debian/pycompat
* Switch from cdbs to dh
* Add watch file
* Build for all supported versions of python2 (closes: 581198, 632240)
* Rename binary package to python-lucene (closes: 581197)
* Add -dbg package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.apache.lucene.search;
 
2
 
 
3
/**
 
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
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
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.
 
18
 */
 
19
 
 
20
import org.apache.lucene.util.LuceneTestCase;
 
21
import org.apache.lucene.document.Document;
 
22
import org.apache.lucene.document.Field;
 
23
import org.apache.lucene.index.IndexReader;
 
24
import org.apache.lucene.index.RandomIndexWriter;
 
25
import org.apache.lucene.index.Term;
 
26
import org.apache.lucene.store.Directory;
 
27
import org.junit.AfterClass;
 
28
import org.junit.BeforeClass;
 
29
 
 
30
import java.text.DecimalFormat;
 
31
import java.util.Random;
 
32
 
 
33
/** Test that BooleanQuery.setMinimumNumberShouldMatch works.
 
34
 */
 
35
public class TestBooleanMinShouldMatch extends LuceneTestCase {
 
36
 
 
37
    private static Directory index;
 
38
    private static IndexReader r;
 
39
    private static IndexSearcher s;
 
40
 
 
41
    @BeforeClass
 
42
    public static void beforeClass() throws Exception {
 
43
        String[] data = new String [] {
 
44
            "A 1 2 3 4 5 6",
 
45
            "Z       4 5 6",
 
46
            null,
 
47
            "B   2   4 5 6",
 
48
            "Y     3   5 6",
 
49
            null,
 
50
            "C     3     6",
 
51
            "X       4 5 6"
 
52
        };
 
53
 
 
54
        index = newDirectory();
 
55
        RandomIndexWriter w = new RandomIndexWriter(random, index);
 
56
 
 
57
        for (int i = 0; i < data.length; i++) {
 
58
            Document doc = new Document();
 
59
            doc.add(newField("id", String.valueOf(i), Field.Store.YES, Field.Index.NOT_ANALYZED));//Field.Keyword("id",String.valueOf(i)));
 
60
            doc.add(newField("all", "all", Field.Store.YES, Field.Index.NOT_ANALYZED));//Field.Keyword("all","all"));
 
61
            if (null != data[i]) {
 
62
                doc.add(newField("data", data[i], Field.Store.YES, Field.Index.ANALYZED));//Field.Text("data",data[i]));
 
63
            }
 
64
            w.addDocument(doc);
 
65
        }
 
66
 
 
67
        r = w.getReader();
 
68
        s = newSearcher(r);
 
69
        w.close();
 
70
//System.out.println("Set up " + getName());
 
71
    }
 
72
    
 
73
    @AfterClass
 
74
    public static void afterClass() throws Exception {
 
75
      s.close();
 
76
      s = null;
 
77
      r.close();
 
78
      r = null;
 
79
      index.close();
 
80
      index = null;
 
81
    }
 
82
 
 
83
 
 
84
    public void verifyNrHits(Query q, int expected) throws Exception {
 
85
        ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
 
86
        if (expected != h.length) {
 
87
            printHits(getName(), h, s);
 
88
        }
 
89
        assertEquals("result count", expected, h.length);
 
90
        QueryUtils.check(random, q,s);
 
91
    }
 
92
 
 
93
    public void testAllOptional() throws Exception {
 
94
 
 
95
        BooleanQuery q = new BooleanQuery();
 
96
        for (int i = 1; i <=4; i++) {
 
97
            q.add(new TermQuery(new Term("data",""+i)), BooleanClause.Occur.SHOULD);//false, false);
 
98
        }
 
99
        q.setMinimumNumberShouldMatch(2); // match at least two of 4
 
100
        verifyNrHits(q, 2);
 
101
    }
 
102
 
 
103
    public void testOneReqAndSomeOptional() throws Exception {
 
104
 
 
105
        /* one required, some optional */
 
106
        BooleanQuery q = new BooleanQuery();
 
107
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.MUST);//true,  false);
 
108
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
109
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
110
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.SHOULD);//false, false);
 
111
 
 
112
        q.setMinimumNumberShouldMatch(2); // 2 of 3 optional 
 
113
 
 
114
        verifyNrHits(q, 5);
 
115
    }
 
116
 
 
117
    public void testSomeReqAndSomeOptional() throws Exception {
 
118
 
 
119
        /* two required, some optional */
 
120
        BooleanQuery q = new BooleanQuery();
 
121
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.MUST);//true,  false);
 
122
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
123
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
124
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
125
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.SHOULD);//false, false);
 
126
 
 
127
        q.setMinimumNumberShouldMatch(2); // 2 of 3 optional 
 
128
 
 
129
        verifyNrHits(q, 5);
 
130
    }
 
131
 
 
132
    public void testOneProhibAndSomeOptional() throws Exception {
 
133
 
 
134
        /* one prohibited, some optional */
 
135
        BooleanQuery q = new BooleanQuery();
 
136
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
137
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
138
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
139
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
140
 
 
141
        q.setMinimumNumberShouldMatch(2); // 2 of 3 optional 
 
142
 
 
143
        verifyNrHits(q, 1);
 
144
    }
 
145
 
 
146
    public void testSomeProhibAndSomeOptional() throws Exception {
 
147
 
 
148
        /* two prohibited, some optional */
 
149
        BooleanQuery q = new BooleanQuery();
 
150
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
151
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
152
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
153
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
154
        q.add(new TermQuery(new Term("data", "C"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
155
 
 
156
        q.setMinimumNumberShouldMatch(2); // 2 of 3 optional 
 
157
 
 
158
        verifyNrHits(q, 1);
 
159
    }
 
160
 
 
161
    public void testOneReqOneProhibAndSomeOptional() throws Exception {
 
162
 
 
163
        /* one required, one prohibited, some optional */
 
164
        BooleanQuery q = new BooleanQuery();
 
165
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);// true,  false);
 
166
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
167
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
168
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
169
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
170
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
171
 
 
172
        q.setMinimumNumberShouldMatch(3); // 3 of 4 optional 
 
173
 
 
174
        verifyNrHits(q, 1);
 
175
    }
 
176
 
 
177
    public void testSomeReqOneProhibAndSomeOptional() throws Exception {
 
178
 
 
179
        /* two required, one prohibited, some optional */
 
180
        BooleanQuery q = new BooleanQuery();
 
181
        q.add(new TermQuery(new Term("all",  "all")), BooleanClause.Occur.MUST);//true,  false);
 
182
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
183
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
184
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
185
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
186
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
187
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
188
 
 
189
        q.setMinimumNumberShouldMatch(3); // 3 of 4 optional 
 
190
 
 
191
        verifyNrHits(q, 1);
 
192
    }
 
193
 
 
194
    public void testOneReqSomeProhibAndSomeOptional() throws Exception {
 
195
 
 
196
        /* one required, two prohibited, some optional */
 
197
        BooleanQuery q = new BooleanQuery();
 
198
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
199
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
200
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
201
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
202
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
203
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
204
        q.add(new TermQuery(new Term("data", "C"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
205
 
 
206
        q.setMinimumNumberShouldMatch(3); // 3 of 4 optional 
 
207
 
 
208
        verifyNrHits(q, 1);
 
209
    }
 
210
 
 
211
    public void testSomeReqSomeProhibAndSomeOptional() throws Exception {
 
212
 
 
213
        /* two required, two prohibited, some optional */
 
214
        BooleanQuery q = new BooleanQuery();
 
215
        q.add(new TermQuery(new Term("all",  "all")), BooleanClause.Occur.MUST);//true,  false);
 
216
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
217
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
218
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
219
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
220
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
221
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
222
        q.add(new TermQuery(new Term("data", "C"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
223
 
 
224
        q.setMinimumNumberShouldMatch(3); // 3 of 4 optional 
 
225
 
 
226
        verifyNrHits(q, 1);
 
227
    }
 
228
 
 
229
    public void testMinHigherThenNumOptional() throws Exception {
 
230
 
 
231
        /* two required, two prohibited, some optional */
 
232
        BooleanQuery q = new BooleanQuery();
 
233
        q.add(new TermQuery(new Term("all",  "all")), BooleanClause.Occur.MUST);//true,  false);
 
234
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
235
        q.add(new TermQuery(new Term("data", "5"  )), BooleanClause.Occur.SHOULD);//false, false);
 
236
        q.add(new TermQuery(new Term("data", "4"  )), BooleanClause.Occur.SHOULD);//false, false);
 
237
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
238
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
239
        q.add(new TermQuery(new Term("data", "1"  )), BooleanClause.Occur.SHOULD);//false, false);
 
240
        q.add(new TermQuery(new Term("data", "C"  )), BooleanClause.Occur.MUST_NOT);//false, true );
 
241
 
 
242
        q.setMinimumNumberShouldMatch(90); // 90 of 4 optional ?!?!?!
 
243
 
 
244
        verifyNrHits(q, 0);
 
245
    }
 
246
 
 
247
    public void testMinEqualToNumOptional() throws Exception {
 
248
 
 
249
        /* two required, two optional */
 
250
        BooleanQuery q = new BooleanQuery();
 
251
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.SHOULD);//false, false);
 
252
        q.add(new TermQuery(new Term("data", "6"  )), BooleanClause.Occur.MUST);//true,  false);
 
253
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.MUST);//true,  false);
 
254
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.SHOULD);//false, false);
 
255
 
 
256
        q.setMinimumNumberShouldMatch(2); // 2 of 2 optional 
 
257
 
 
258
        verifyNrHits(q, 1);
 
259
    }
 
260
 
 
261
    public void testOneOptionalEqualToMin() throws Exception {
 
262
 
 
263
        /* two required, one optional */
 
264
        BooleanQuery q = new BooleanQuery();
 
265
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.MUST);//true,  false);
 
266
        q.add(new TermQuery(new Term("data", "3"  )), BooleanClause.Occur.SHOULD);//false, false);
 
267
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.MUST);//true,  false);
 
268
 
 
269
        q.setMinimumNumberShouldMatch(1); // 1 of 1 optional 
 
270
 
 
271
        verifyNrHits(q, 1);
 
272
    }
 
273
 
 
274
    public void testNoOptionalButMin() throws Exception {
 
275
 
 
276
        /* two required, no optional */
 
277
        BooleanQuery q = new BooleanQuery();
 
278
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.MUST);//true,  false);
 
279
        q.add(new TermQuery(new Term("data", "2"  )), BooleanClause.Occur.MUST);//true,  false);
 
280
 
 
281
        q.setMinimumNumberShouldMatch(1); // 1 of 0 optional 
 
282
 
 
283
        verifyNrHits(q, 0);
 
284
    }
 
285
 
 
286
    public void testNoOptionalButMin2() throws Exception {
 
287
 
 
288
        /* one required, no optional */
 
289
        BooleanQuery q = new BooleanQuery();
 
290
        q.add(new TermQuery(new Term("all", "all" )), BooleanClause.Occur.MUST);//true,  false);
 
291
 
 
292
        q.setMinimumNumberShouldMatch(1); // 1 of 0 optional 
 
293
 
 
294
        verifyNrHits(q, 0);
 
295
    }
 
296
 
 
297
    public void testRandomQueries() throws Exception {
 
298
      String field="data";
 
299
      String[] vals = {"1","2","3","4","5","6","A","Z","B","Y","Z","X","foo"};
 
300
      int maxLev=4;
 
301
 
 
302
      // callback object to set a random setMinimumNumberShouldMatch
 
303
      TestBoolean2.Callback minNrCB = new TestBoolean2.Callback() {
 
304
        public void postCreate(BooleanQuery q) {
 
305
          BooleanClause[] c =q.getClauses();
 
306
          int opt=0;
 
307
          for (int i=0; i<c.length;i++) {
 
308
            if (c[i].getOccur() == BooleanClause.Occur.SHOULD) opt++;
 
309
          }
 
310
          q.setMinimumNumberShouldMatch(random.nextInt(opt+2));
 
311
        }
 
312
      };
 
313
 
 
314
 
 
315
 
 
316
      // increase number of iterations for more complete testing      
 
317
      int num = atLeast(10);
 
318
      for (int i = 0; i < num; i++) {
 
319
        int lev = random.nextInt(maxLev);
 
320
        final long seed = random.nextLong();
 
321
        BooleanQuery q1 = TestBoolean2.randBoolQuery(new Random(seed), true, lev, field, vals, null);
 
322
        // BooleanQuery q2 = TestBoolean2.randBoolQuery(new Random(seed), lev, field, vals, minNrCB);
 
323
        BooleanQuery q2 = TestBoolean2.randBoolQuery(new Random(seed), true, lev, field, vals, null);
 
324
        // only set minimumNumberShouldMatch on the top level query since setting
 
325
        // at a lower level can change the score.
 
326
        minNrCB.postCreate(q2);
 
327
 
 
328
        // Can't use Hits because normalized scores will mess things
 
329
        // up.  The non-sorting version of search() that returns TopDocs
 
330
        // will not normalize scores.
 
331
        TopDocs top1 = s.search(q1,null,100);
 
332
        TopDocs top2 = s.search(q2,null,100);
 
333
        if (i < 100) {
 
334
          QueryUtils.check(random, q1,s);
 
335
          QueryUtils.check(random, q2,s);
 
336
        }
 
337
        // The constrained query
 
338
        // should be a superset to the unconstrained query.
 
339
        if (top2.totalHits > top1.totalHits) {
 
340
          fail("Constrained results not a subset:\n"
 
341
                        + CheckHits.topdocsString(top1,0,0)
 
342
                        + CheckHits.topdocsString(top2,0,0)
 
343
                        + "for query:" + q2.toString());
 
344
        }
 
345
 
 
346
        for (int hit=0; hit<top2.totalHits; hit++) {
 
347
          int id = top2.scoreDocs[hit].doc;
 
348
          float score = top2.scoreDocs[hit].score;
 
349
          boolean found=false;
 
350
          // find this doc in other hits
 
351
          for (int other=0; other<top1.totalHits; other++) {
 
352
            if (top1.scoreDocs[other].doc == id) {
 
353
              found=true;
 
354
              float otherScore = top1.scoreDocs[other].score;
 
355
              // check if scores match
 
356
              if (Math.abs(otherScore-score)>1.0e-6f) {
 
357
                        fail("Doc " + id + " scores don't match\n"
 
358
                + CheckHits.topdocsString(top1,0,0)
 
359
                + CheckHits.topdocsString(top2,0,0)
 
360
                + "for query:" + q2.toString());
 
361
              }
 
362
            }
 
363
          }
 
364
 
 
365
          // check if subset
 
366
          if (!found) fail("Doc " + id + " not found\n"
 
367
                + CheckHits.topdocsString(top1,0,0)
 
368
                + CheckHits.topdocsString(top2,0,0)
 
369
                + "for query:" + q2.toString());
 
370
        }
 
371
      }
 
372
      // System.out.println("Total hits:"+tot);
 
373
    }
 
374
 
 
375
 
 
376
 
 
377
    protected void printHits(String test, ScoreDoc[] h, Searcher searcher) throws Exception {
 
378
 
 
379
        System.err.println("------- " + test + " -------");
 
380
 
 
381
        DecimalFormat f = new DecimalFormat("0.000000");
 
382
 
 
383
        for (int i = 0; i < h.length; i++) {
 
384
            Document d = searcher.doc(h[i].doc);
 
385
            float score = h[i].score;
 
386
            System.err.println("#" + i + ": " + f.format(score) + " - " +
 
387
                               d.get("id") + " - " + d.get("data"));
 
388
        }
 
389
    }
 
390
}