~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/backwards/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

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.analysis.MockAnalyzer;
22
 
import org.apache.lucene.analysis.WhitespaceAnalyzer;
23
 
import org.apache.lucene.document.Document;
24
 
import org.apache.lucene.document.Field;
25
 
import org.apache.lucene.index.IndexReader;
26
 
import org.apache.lucene.index.FieldInvertState;
27
 
import org.apache.lucene.index.RandomIndexWriter;
28
 
import org.apache.lucene.index.Term;
29
 
import org.apache.lucene.store.Directory;
30
 
 
31
 
import java.text.DecimalFormat;
32
 
import java.io.IOException;
33
 
 
34
 
/**
35
 
 * Test of the DisjunctionMaxQuery.
36
 
 * 
37
 
 */
38
 
public class TestDisjunctionMaxQuery extends LuceneTestCase {
39
 
  
40
 
  /** threshold for comparing floats */
41
 
  public static final float SCORE_COMP_THRESH = 0.0000f;
42
 
  
43
 
  /**
44
 
   * Similarity to eliminate tf, idf and lengthNorm effects to isolate test
45
 
   * case.
46
 
   * 
47
 
   * <p>
48
 
   * same as TestRankingSimilarity in TestRanking.zip from
49
 
   * http://issues.apache.org/jira/browse/LUCENE-323
50
 
   * </p>
51
 
   */
52
 
  private static class TestSimilarity extends DefaultSimilarity {
53
 
    
54
 
    public TestSimilarity() {}
55
 
    
56
 
    @Override
57
 
    public float tf(float freq) {
58
 
      if (freq > 0.0f) return 1.0f;
59
 
      else return 0.0f;
60
 
    }
61
 
    
62
 
    @Override
63
 
    public float computeNorm(String fieldName, FieldInvertState state) {
64
 
      // Disable length norm
65
 
      return state.getBoost();
66
 
    }
67
 
    
68
 
    @Override
69
 
    public float idf(int docFreq, int numDocs) {
70
 
      return 1.0f;
71
 
    }
72
 
  }
73
 
  
74
 
  public Similarity sim = new TestSimilarity();
75
 
  public Directory index;
76
 
  public IndexReader r;
77
 
  public IndexSearcher s;
78
 
  
79
 
  @Override
80
 
  public void setUp() throws Exception {
81
 
    super.setUp();
82
 
    
83
 
    index = newDirectory();
84
 
    RandomIndexWriter writer = new RandomIndexWriter(random, index,
85
 
        newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random))
86
 
                                                     .setSimilarity(sim).setMergePolicy(newLogMergePolicy()));
87
 
    
88
 
    // hed is the most important field, dek is secondary
89
 
    
90
 
    // d1 is an "ok" match for: albino elephant
91
 
    {
92
 
      Document d1 = new Document();
93
 
      d1.add(newField("id", "d1", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
94
 
                                                                               // "d1"));
95
 
      d1
96
 
          .add(newField("hed", "elephant", Field.Store.YES,
97
 
              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
98
 
      d1
99
 
          .add(newField("dek", "elephant", Field.Store.YES,
100
 
              Field.Index.ANALYZED));// Field.Text("dek", "elephant"));
101
 
      writer.addDocument(d1);
102
 
    }
103
 
    
104
 
    // d2 is a "good" match for: albino elephant
105
 
    {
106
 
      Document d2 = new Document();
107
 
      d2.add(newField("id", "d2", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
108
 
                                                                               // "d2"));
109
 
      d2
110
 
          .add(newField("hed", "elephant", Field.Store.YES,
111
 
              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
112
 
      d2.add(newField("dek", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("dek",
113
 
                                                                                // "albino"));
114
 
      d2
115
 
          .add(newField("dek", "elephant", Field.Store.YES,
116
 
              Field.Index.ANALYZED));// Field.Text("dek", "elephant"));
117
 
      writer.addDocument(d2);
118
 
    }
119
 
    
120
 
    // d3 is a "better" match for: albino elephant
121
 
    {
122
 
      Document d3 = new Document();
123
 
      d3.add(newField("id", "d3", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
124
 
                                                                               // "d3"));
125
 
      d3.add(newField("hed", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("hed",
126
 
                                                                                // "albino"));
127
 
      d3
128
 
          .add(newField("hed", "elephant", Field.Store.YES,
129
 
              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
130
 
      writer.addDocument(d3);
131
 
    }
132
 
    
133
 
    // d4 is the "best" match for: albino elephant
134
 
    {
135
 
      Document d4 = new Document();
136
 
      d4.add(newField("id", "d4", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
137
 
                                                                               // "d4"));
138
 
      d4.add(newField("hed", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("hed",
139
 
                                                                                // "albino"));
140
 
      d4
141
 
          .add(newField("hed", "elephant", Field.Store.YES,
142
 
              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
143
 
      d4.add(newField("dek", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("dek",
144
 
                                                                                // "albino"));
145
 
      writer.addDocument(d4);
146
 
    }
147
 
 
148
 
    writer.optimize();
149
 
    r = writer.getReader();
150
 
    writer.close();
151
 
    s = newSearcher(r);
152
 
    s.setSimilarity(sim);
153
 
  }
154
 
  
155
 
  @Override
156
 
  public void tearDown() throws Exception {
157
 
    s.close();
158
 
    r.close();
159
 
    index.close();
160
 
    super.tearDown();
161
 
  }
162
 
  
163
 
  public void testSkipToFirsttimeMiss() throws IOException {
164
 
    final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f);
165
 
    dq.add(tq("id", "d1"));
166
 
    dq.add(tq("dek", "DOES_NOT_EXIST"));
167
 
    
168
 
    QueryUtils.check(random, dq, s);
169
 
    
170
 
    final Weight dw = s.createNormalizedWeight(dq);
171
 
    IndexReader sub = s.getIndexReader().getSequentialSubReaders() == null ?
172
 
        s.getIndexReader() : s.getIndexReader().getSequentialSubReaders()[0];
173
 
    final Scorer ds = dw.scorer(sub, true, false);
174
 
    final boolean skipOk = ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS;
175
 
    if (skipOk) {
176
 
      fail("firsttime skipTo found a match? ... "
177
 
          + r.document(ds.docID()).get("id"));
178
 
    }
179
 
  }
180
 
  
181
 
  public void testSkipToFirsttimeHit() throws IOException {
182
 
    final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f);
183
 
    dq.add(tq("dek", "albino"));
184
 
    dq.add(tq("dek", "DOES_NOT_EXIST"));
185
 
    
186
 
    QueryUtils.check(random, dq, s);
187
 
 
188
 
    final Weight dw = s.createNormalizedWeight(dq);
189
 
    IndexReader sub = s.getIndexReader().getSequentialSubReaders() == null ?
190
 
        s.getIndexReader() : s.getIndexReader().getSequentialSubReaders()[0];
191
 
    final Scorer ds = dw.scorer(sub, true, false);
192
 
    assertTrue("firsttime skipTo found no match",
193
 
        ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS);
194
 
    assertEquals("found wrong docid", "d4", r.document(ds.docID()).get("id"));
195
 
  }
196
 
  
197
 
  public void testSimpleEqualScores1() throws Exception {
198
 
    
199
 
    DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f);
200
 
    q.add(tq("hed", "albino"));
201
 
    q.add(tq("hed", "elephant"));
202
 
    QueryUtils.check(random, q, s);
203
 
    
204
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
205
 
    
206
 
    try {
207
 
      assertEquals("all docs should match " + q.toString(), 4, h.length);
208
 
      
209
 
      float score = h[0].score;
210
 
      for (int i = 1; i < h.length; i++) {
211
 
        assertEquals("score #" + i + " is not the same", score, h[i].score,
212
 
            SCORE_COMP_THRESH);
213
 
      }
214
 
    } catch (Error e) {
215
 
      printHits("testSimpleEqualScores1", h, s);
216
 
      throw e;
217
 
    }
218
 
    
219
 
  }
220
 
  
221
 
  public void testSimpleEqualScores2() throws Exception {
222
 
    
223
 
    DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f);
224
 
    q.add(tq("dek", "albino"));
225
 
    q.add(tq("dek", "elephant"));
226
 
    QueryUtils.check(random, q, s);
227
 
    
228
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
229
 
    
230
 
    try {
231
 
      assertEquals("3 docs should match " + q.toString(), 3, h.length);
232
 
      float score = h[0].score;
233
 
      for (int i = 1; i < h.length; i++) {
234
 
        assertEquals("score #" + i + " is not the same", score, h[i].score,
235
 
            SCORE_COMP_THRESH);
236
 
      }
237
 
    } catch (Error e) {
238
 
      printHits("testSimpleEqualScores2", h, s);
239
 
      throw e;
240
 
    }
241
 
    
242
 
  }
243
 
  
244
 
  public void testSimpleEqualScores3() throws Exception {
245
 
    
246
 
    DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f);
247
 
    q.add(tq("hed", "albino"));
248
 
    q.add(tq("hed", "elephant"));
249
 
    q.add(tq("dek", "albino"));
250
 
    q.add(tq("dek", "elephant"));
251
 
    QueryUtils.check(random, q, s);
252
 
    
253
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
254
 
    
255
 
    try {
256
 
      assertEquals("all docs should match " + q.toString(), 4, h.length);
257
 
      float score = h[0].score;
258
 
      for (int i = 1; i < h.length; i++) {
259
 
        assertEquals("score #" + i + " is not the same", score, h[i].score,
260
 
            SCORE_COMP_THRESH);
261
 
      }
262
 
    } catch (Error e) {
263
 
      printHits("testSimpleEqualScores3", h, s);
264
 
      throw e;
265
 
    }
266
 
    
267
 
  }
268
 
  
269
 
  public void testSimpleTiebreaker() throws Exception {
270
 
    
271
 
    DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.01f);
272
 
    q.add(tq("dek", "albino"));
273
 
    q.add(tq("dek", "elephant"));
274
 
    QueryUtils.check(random, q, s);
275
 
    
276
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
277
 
    
278
 
    try {
279
 
      assertEquals("3 docs should match " + q.toString(), 3, h.length);
280
 
      assertEquals("wrong first", "d2", s.doc(h[0].doc).get("id"));
281
 
      float score0 = h[0].score;
282
 
      float score1 = h[1].score;
283
 
      float score2 = h[2].score;
284
 
      assertTrue("d2 does not have better score then others: " + score0
285
 
          + " >? " + score1, score0 > score1);
286
 
      assertEquals("d4 and d1 don't have equal scores", score1, score2,
287
 
          SCORE_COMP_THRESH);
288
 
    } catch (Error e) {
289
 
      printHits("testSimpleTiebreaker", h, s);
290
 
      throw e;
291
 
    }
292
 
  }
293
 
  
294
 
  public void testBooleanRequiredEqualScores() throws Exception {
295
 
    
296
 
    BooleanQuery q = new BooleanQuery();
297
 
    {
298
 
      DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f);
299
 
      q1.add(tq("hed", "albino"));
300
 
      q1.add(tq("dek", "albino"));
301
 
      q.add(q1, BooleanClause.Occur.MUST);// true,false);
302
 
      QueryUtils.check(random, q1, s);
303
 
      
304
 
    }
305
 
    {
306
 
      DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f);
307
 
      q2.add(tq("hed", "elephant"));
308
 
      q2.add(tq("dek", "elephant"));
309
 
      q.add(q2, BooleanClause.Occur.MUST);// true,false);
310
 
      QueryUtils.check(random, q2, s);
311
 
    }
312
 
    
313
 
    QueryUtils.check(random, q, s);
314
 
    
315
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
316
 
    
317
 
    try {
318
 
      assertEquals("3 docs should match " + q.toString(), 3, h.length);
319
 
      float score = h[0].score;
320
 
      for (int i = 1; i < h.length; i++) {
321
 
        assertEquals("score #" + i + " is not the same", score, h[i].score,
322
 
            SCORE_COMP_THRESH);
323
 
      }
324
 
    } catch (Error e) {
325
 
      printHits("testBooleanRequiredEqualScores1", h, s);
326
 
      throw e;
327
 
    }
328
 
  }
329
 
  
330
 
  public void testBooleanOptionalNoTiebreaker() throws Exception {
331
 
    
332
 
    BooleanQuery q = new BooleanQuery();
333
 
    {
334
 
      DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f);
335
 
      q1.add(tq("hed", "albino"));
336
 
      q1.add(tq("dek", "albino"));
337
 
      q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
338
 
    }
339
 
    {
340
 
      DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f);
341
 
      q2.add(tq("hed", "elephant"));
342
 
      q2.add(tq("dek", "elephant"));
343
 
      q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
344
 
    }
345
 
    QueryUtils.check(random, q, s);
346
 
    
347
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
348
 
    
349
 
    try {
350
 
      assertEquals("4 docs should match " + q.toString(), 4, h.length);
351
 
      float score = h[0].score;
352
 
      for (int i = 1; i < h.length - 1; i++) { /* note: -1 */
353
 
        assertEquals("score #" + i + " is not the same", score, h[i].score,
354
 
            SCORE_COMP_THRESH);
355
 
      }
356
 
      assertEquals("wrong last", "d1", s.doc(h[h.length - 1].doc).get("id"));
357
 
      float score1 = h[h.length - 1].score;
358
 
      assertTrue("d1 does not have worse score then others: " + score + " >? "
359
 
          + score1, score > score1);
360
 
    } catch (Error e) {
361
 
      printHits("testBooleanOptionalNoTiebreaker", h, s);
362
 
      throw e;
363
 
    }
364
 
  }
365
 
  
366
 
  public void testBooleanOptionalWithTiebreaker() throws Exception {
367
 
    
368
 
    BooleanQuery q = new BooleanQuery();
369
 
    {
370
 
      DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f);
371
 
      q1.add(tq("hed", "albino"));
372
 
      q1.add(tq("dek", "albino"));
373
 
      q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
374
 
    }
375
 
    {
376
 
      DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f);
377
 
      q2.add(tq("hed", "elephant"));
378
 
      q2.add(tq("dek", "elephant"));
379
 
      q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
380
 
    }
381
 
    QueryUtils.check(random, q, s);
382
 
    
383
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
384
 
    
385
 
    try {
386
 
      
387
 
      assertEquals("4 docs should match " + q.toString(), 4, h.length);
388
 
      
389
 
      float score0 = h[0].score;
390
 
      float score1 = h[1].score;
391
 
      float score2 = h[2].score;
392
 
      float score3 = h[3].score;
393
 
      
394
 
      String doc0 = s.doc(h[0].doc).get("id");
395
 
      String doc1 = s.doc(h[1].doc).get("id");
396
 
      String doc2 = s.doc(h[2].doc).get("id");
397
 
      String doc3 = s.doc(h[3].doc).get("id");
398
 
      
399
 
      assertTrue("doc0 should be d2 or d4: " + doc0, doc0.equals("d2")
400
 
          || doc0.equals("d4"));
401
 
      assertTrue("doc1 should be d2 or d4: " + doc0, doc1.equals("d2")
402
 
          || doc1.equals("d4"));
403
 
      assertEquals("score0 and score1 should match", score0, score1,
404
 
          SCORE_COMP_THRESH);
405
 
      assertEquals("wrong third", "d3", doc2);
406
 
      assertTrue("d3 does not have worse score then d2 and d4: " + score1
407
 
          + " >? " + score2, score1 > score2);
408
 
      
409
 
      assertEquals("wrong fourth", "d1", doc3);
410
 
      assertTrue("d1 does not have worse score then d3: " + score2 + " >? "
411
 
          + score3, score2 > score3);
412
 
      
413
 
    } catch (Error e) {
414
 
      printHits("testBooleanOptionalWithTiebreaker", h, s);
415
 
      throw e;
416
 
    }
417
 
    
418
 
  }
419
 
  
420
 
  public void testBooleanOptionalWithTiebreakerAndBoost() throws Exception {
421
 
    
422
 
    BooleanQuery q = new BooleanQuery();
423
 
    {
424
 
      DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f);
425
 
      q1.add(tq("hed", "albino", 1.5f));
426
 
      q1.add(tq("dek", "albino"));
427
 
      q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
428
 
    }
429
 
    {
430
 
      DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f);
431
 
      q2.add(tq("hed", "elephant", 1.5f));
432
 
      q2.add(tq("dek", "elephant"));
433
 
      q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
434
 
    }
435
 
    QueryUtils.check(random, q, s);
436
 
    
437
 
    ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
438
 
    
439
 
    try {
440
 
      
441
 
      assertEquals("4 docs should match " + q.toString(), 4, h.length);
442
 
      
443
 
      float score0 = h[0].score;
444
 
      float score1 = h[1].score;
445
 
      float score2 = h[2].score;
446
 
      float score3 = h[3].score;
447
 
      
448
 
      String doc0 = s.doc(h[0].doc).get("id");
449
 
      String doc1 = s.doc(h[1].doc).get("id");
450
 
      String doc2 = s.doc(h[2].doc).get("id");
451
 
      String doc3 = s.doc(h[3].doc).get("id");
452
 
      
453
 
      assertEquals("doc0 should be d4: ", "d4", doc0);
454
 
      assertEquals("doc1 should be d3: ", "d3", doc1);
455
 
      assertEquals("doc2 should be d2: ", "d2", doc2);
456
 
      assertEquals("doc3 should be d1: ", "d1", doc3);
457
 
      
458
 
      assertTrue("d4 does not have a better score then d3: " + score0 + " >? "
459
 
          + score1, score0 > score1);
460
 
      assertTrue("d3 does not have a better score then d2: " + score1 + " >? "
461
 
          + score2, score1 > score2);
462
 
      assertTrue("d3 does not have a better score then d1: " + score2 + " >? "
463
 
          + score3, score2 > score3);
464
 
      
465
 
    } catch (Error e) {
466
 
      printHits("testBooleanOptionalWithTiebreakerAndBoost", h, s);
467
 
      throw e;
468
 
    }
469
 
  }
470
 
  
471
 
  /** macro */
472
 
  protected Query tq(String f, String t) {
473
 
    return new TermQuery(new Term(f, t));
474
 
  }
475
 
  
476
 
  /** macro */
477
 
  protected Query tq(String f, String t, float b) {
478
 
    Query q = tq(f, t);
479
 
    q.setBoost(b);
480
 
    return q;
481
 
  }
482
 
  
483
 
  protected void printHits(String test, ScoreDoc[] h, Searcher searcher)
484
 
      throws Exception {
485
 
    
486
 
    System.err.println("------- " + test + " -------");
487
 
    
488
 
    DecimalFormat f = new DecimalFormat("0.000000000");
489
 
    
490
 
    for (int i = 0; i < h.length; i++) {
491
 
      Document d = searcher.doc(h[i].doc);
492
 
      float score = h[i].score;
493
 
      System.err
494
 
          .println("#" + i + ": " + f.format(score) + " - " + d.get("id"));
495
 
    }
496
 
  }
497
 
}