pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / backwards / src / test / org / apache / lucene / search / spans / TestSpans.java
1 package org.apache.lucene.search.spans;
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.search.DocIdSetIterator;
21 import org.apache.lucene.search.IndexSearcher;
22 import org.apache.lucene.search.Query;
23 import org.apache.lucene.search.CheckHits;
24 import org.apache.lucene.search.Similarity;
25 import org.apache.lucene.search.DefaultSimilarity;
26 import org.apache.lucene.search.Scorer;
27 import org.apache.lucene.search.TermQuery;
28 import org.apache.lucene.search.Searcher;
29 import org.apache.lucene.store.Directory;
30 import org.apache.lucene.analysis.MockAnalyzer;
31 import org.apache.lucene.index.IndexWriter;
32 import org.apache.lucene.index.IndexReader;
33 import org.apache.lucene.index.IndexWriterConfig;
34 import org.apache.lucene.index.RandomIndexWriter;
35 import org.apache.lucene.index.Term;
36 import org.apache.lucene.document.Document;
37 import org.apache.lucene.document.Field;
38 import org.apache.lucene.util.LuceneTestCase;
39 import java.io.IOException;
40
41 public class TestSpans extends LuceneTestCase {
42   private IndexSearcher searcher;
43   private IndexReader reader;
44   private Directory directory;
45   
46   public static final String field = "field";
47
48   @Override
49   public void setUp() throws Exception {
50     super.setUp();
51     directory = newDirectory();
52     RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
53     for (int i = 0; i < docFields.length; i++) {
54       Document doc = new Document();
55       doc.add(newField(field, docFields[i], Field.Store.YES, Field.Index.ANALYZED));
56       writer.addDocument(doc);
57     }
58     reader = writer.getReader();
59     writer.close();
60     searcher = newSearcher(reader);
61   }
62   
63   @Override
64   public void tearDown() throws Exception {
65     searcher.close();
66     reader.close();
67     directory.close();
68     super.tearDown();
69   }
70   
71   private String[] docFields = {
72     "w1 w2 w3 w4 w5",
73     "w1 w3 w2 w3",
74     "w1 xx w2 yy w3",
75     "w1 w3 xx w2 yy w3",
76     "u2 u2 u1",
77     "u2 xx u2 u1",
78     "u2 u2 xx u1",
79     "u2 xx u2 yy u1",
80     "u2 xx u1 u2",
81     "u2 u1 xx u2",
82     "u1 u2 xx u2",
83     "t1 t2 t1 t3 t2 t3"
84   };
85
86   public SpanTermQuery makeSpanTermQuery(String text) {
87     return new SpanTermQuery(new Term(field, text));
88   }
89   
90   private void checkHits(Query query, int[] results) throws IOException {
91     CheckHits.checkHits(random, query, field, searcher, results);
92   }
93   
94   private void orderedSlopTest3SQ(
95         SpanQuery q1,
96         SpanQuery q2,
97         SpanQuery q3,
98         int slop,
99         int[] expectedDocs) throws IOException {
100     boolean ordered = true;
101     SpanNearQuery snq = new SpanNearQuery( new SpanQuery[]{q1,q2,q3}, slop, ordered);
102     checkHits(snq, expectedDocs);
103   }
104   
105   public void orderedSlopTest3(int slop, int[] expectedDocs) throws IOException {
106     orderedSlopTest3SQ(
107        makeSpanTermQuery("w1"),
108        makeSpanTermQuery("w2"),
109        makeSpanTermQuery("w3"),
110        slop,
111        expectedDocs);
112   }
113   
114   public void orderedSlopTest3Equal(int slop, int[] expectedDocs) throws IOException {
115     orderedSlopTest3SQ(
116        makeSpanTermQuery("w1"),
117        makeSpanTermQuery("w3"),
118        makeSpanTermQuery("w3"),
119        slop,
120        expectedDocs);
121   }
122   
123   public void orderedSlopTest1Equal(int slop, int[] expectedDocs) throws IOException {
124     orderedSlopTest3SQ(
125        makeSpanTermQuery("u2"),
126        makeSpanTermQuery("u2"),
127        makeSpanTermQuery("u1"),
128        slop,
129        expectedDocs);
130   }
131   
132   public void testSpanNearOrdered01() throws Exception {
133     orderedSlopTest3(0, new int[] {0});
134   }
135
136   public void testSpanNearOrdered02() throws Exception {
137     orderedSlopTest3(1, new int[] {0,1});
138   }
139
140   public void testSpanNearOrdered03() throws Exception {
141     orderedSlopTest3(2, new int[] {0,1,2});
142   }
143
144   public void testSpanNearOrdered04() throws Exception {
145     orderedSlopTest3(3, new int[] {0,1,2,3});
146   }
147
148   public void testSpanNearOrdered05() throws Exception {
149     orderedSlopTest3(4, new int[] {0,1,2,3});
150   }
151   
152   public void testSpanNearOrderedEqual01() throws Exception {
153     orderedSlopTest3Equal(0, new int[] {});
154   }
155
156   public void testSpanNearOrderedEqual02() throws Exception {
157     orderedSlopTest3Equal(1, new int[] {1});
158   }
159
160   public void testSpanNearOrderedEqual03() throws Exception {
161     orderedSlopTest3Equal(2, new int[] {1});
162   }
163
164   public void testSpanNearOrderedEqual04() throws Exception {
165     orderedSlopTest3Equal(3, new int[] {1,3});
166   }
167   
168   public void testSpanNearOrderedEqual11() throws Exception {
169     orderedSlopTest1Equal(0, new int[] {4});
170   }
171   
172   public void testSpanNearOrderedEqual12() throws Exception {
173     orderedSlopTest1Equal(0, new int[] {4});
174   }
175   
176   public void testSpanNearOrderedEqual13() throws Exception {
177     orderedSlopTest1Equal(1, new int[] {4,5,6});
178   }
179   
180   public void testSpanNearOrderedEqual14() throws Exception {
181     orderedSlopTest1Equal(2, new int[] {4,5,6,7});
182   }
183
184   public void testSpanNearOrderedEqual15() throws Exception {
185     orderedSlopTest1Equal(3, new int[] {4,5,6,7});
186   }
187
188   public void testSpanNearOrderedOverlap() throws Exception {
189     boolean ordered = true;
190     int slop = 1;
191     SpanNearQuery snq = new SpanNearQuery(
192                               new SpanQuery[] {
193                                 makeSpanTermQuery("t1"),
194                                 makeSpanTermQuery("t2"),
195                                 makeSpanTermQuery("t3") },
196                               slop,
197                               ordered);
198     Spans spans = snq.getSpans(searcher.getIndexReader());
199
200     assertTrue("first range", spans.next());
201     assertEquals("first doc", 11, spans.doc());
202     assertEquals("first start", 0, spans.start());
203     assertEquals("first end", 4, spans.end());
204
205     assertTrue("second range", spans.next());
206     assertEquals("second doc", 11, spans.doc());
207     assertEquals("second start", 2, spans.start());
208     assertEquals("second end", 6, spans.end());
209
210     assertFalse("third range", spans.next());
211   }
212
213
214   public void testSpanNearUnOrdered() throws Exception {
215
216     //See http://www.gossamer-threads.com/lists/lucene/java-dev/52270 for discussion about this test
217     SpanNearQuery snq;
218     snq = new SpanNearQuery(
219                               new SpanQuery[] {
220                                 makeSpanTermQuery("u1"),
221                                 makeSpanTermQuery("u2") },
222                               0,
223                               false);
224     Spans spans = snq.getSpans(searcher.getIndexReader());
225     assertTrue("Does not have next and it should", spans.next());
226     assertEquals("doc", 4, spans.doc());
227     assertEquals("start", 1, spans.start());
228     assertEquals("end", 3, spans.end());
229
230     assertTrue("Does not have next and it should", spans.next());
231     assertEquals("doc", 5, spans.doc());
232     assertEquals("start", 2, spans.start());
233     assertEquals("end", 4, spans.end());
234
235     assertTrue("Does not have next and it should", spans.next());
236     assertEquals("doc", 8, spans.doc());
237     assertEquals("start", 2, spans.start());
238     assertEquals("end", 4, spans.end());
239
240     assertTrue("Does not have next and it should", spans.next());
241     assertEquals("doc", 9, spans.doc());
242     assertEquals("start", 0, spans.start());
243     assertEquals("end", 2, spans.end());
244
245     assertTrue("Does not have next and it should", spans.next());
246     assertEquals("doc", 10, spans.doc());
247     assertEquals("start", 0, spans.start());
248     assertEquals("end", 2, spans.end());
249     assertTrue("Has next and it shouldn't: " + spans.doc(), spans.next() == false);
250
251     SpanNearQuery u1u2 = new SpanNearQuery(new SpanQuery[]{makeSpanTermQuery("u1"),
252                                 makeSpanTermQuery("u2")}, 0, false);
253     snq = new SpanNearQuery(
254                               new SpanQuery[] {
255                                 u1u2,
256                                 makeSpanTermQuery("u2")
257                               },
258                               1,
259                               false);
260     spans = snq.getSpans(searcher.getIndexReader());
261     assertTrue("Does not have next and it should", spans.next());
262     assertEquals("doc", 4, spans.doc());
263     assertEquals("start", 0, spans.start());
264     assertEquals("end", 3, spans.end());
265
266     assertTrue("Does not have next and it should", spans.next());
267     //unordered spans can be subsets
268     assertEquals("doc", 4, spans.doc());
269     assertEquals("start", 1, spans.start());
270     assertEquals("end", 3, spans.end());
271
272     assertTrue("Does not have next and it should", spans.next());
273     assertEquals("doc", 5, spans.doc());
274     assertEquals("start", 0, spans.start());
275     assertEquals("end", 4, spans.end());
276
277     assertTrue("Does not have next and it should", spans.next());
278     assertEquals("doc", 5, spans.doc());
279     assertEquals("start", 2, spans.start());
280     assertEquals("end", 4, spans.end());
281
282     assertTrue("Does not have next and it should", spans.next());
283     assertEquals("doc", 8, spans.doc());
284     assertEquals("start", 0, spans.start());
285     assertEquals("end", 4, spans.end());
286
287
288     assertTrue("Does not have next and it should", spans.next());
289     assertEquals("doc", 8, spans.doc());
290     assertEquals("start", 2, spans.start());
291     assertEquals("end", 4, spans.end());
292
293     assertTrue("Does not have next and it should", spans.next());
294     assertEquals("doc", 9, spans.doc());
295     assertEquals("start", 0, spans.start());
296     assertEquals("end", 2, spans.end());
297
298     assertTrue("Does not have next and it should", spans.next());
299     assertEquals("doc", 9, spans.doc());
300     assertEquals("start", 0, spans.start());
301     assertEquals("end", 4, spans.end());
302
303     assertTrue("Does not have next and it should", spans.next());
304     assertEquals("doc", 10, spans.doc());
305     assertEquals("start", 0, spans.start());
306     assertEquals("end", 2, spans.end());
307
308     assertTrue("Has next and it shouldn't", spans.next() == false);
309   }
310
311
312
313   private Spans orSpans(String[] terms) throws Exception {
314     SpanQuery[] sqa = new SpanQuery[terms.length];
315     for (int i = 0; i < terms.length; i++) {
316       sqa[i] = makeSpanTermQuery(terms[i]);
317     }
318     return (new SpanOrQuery(sqa)).getSpans(searcher.getIndexReader());
319   }
320
321   private void tstNextSpans(Spans spans, int doc, int start, int end)
322   throws Exception {
323     assertTrue("next", spans.next());
324     assertEquals("doc", doc, spans.doc());
325     assertEquals("start", start, spans.start());
326     assertEquals("end", end, spans.end());
327   }
328
329   public void testSpanOrEmpty() throws Exception {
330     Spans spans = orSpans(new String[0]);
331     assertFalse("empty next", spans.next());
332
333     SpanOrQuery a = new SpanOrQuery( new SpanQuery[0] );
334     SpanOrQuery b = new SpanOrQuery( new SpanQuery[0] );
335     assertTrue("empty should equal", a.equals(b));
336   }
337
338   public void testSpanOrSingle() throws Exception {
339     Spans spans = orSpans(new String[] {"w5"});
340     tstNextSpans(spans, 0, 4, 5);
341     assertFalse("final next", spans.next());
342   }
343   
344   public void testSpanOrMovesForward() throws Exception {
345     Spans spans = orSpans(new String[] {"w1", "xx"});
346
347     spans.next();
348     int doc = spans.doc();
349     assertEquals(0, doc);
350     
351     spans.skipTo(0);
352     doc = spans.doc();
353     
354     // LUCENE-1583:
355     // according to Spans, a skipTo to the same doc or less
356     // should still call next() on the underlying Spans
357     assertEquals(1, doc);
358
359   }
360   
361   public void testSpanOrDouble() throws Exception {
362     Spans spans = orSpans(new String[] {"w5", "yy"});
363     tstNextSpans(spans, 0, 4, 5);
364     tstNextSpans(spans, 2, 3, 4);
365     tstNextSpans(spans, 3, 4, 5);
366     tstNextSpans(spans, 7, 3, 4);
367     assertFalse("final next", spans.next());
368   }
369
370   public void testSpanOrDoubleSkip() throws Exception {
371     Spans spans = orSpans(new String[] {"w5", "yy"});
372     assertTrue("initial skipTo", spans.skipTo(3));
373     assertEquals("doc", 3, spans.doc());
374     assertEquals("start", 4, spans.start());
375     assertEquals("end", 5, spans.end());
376     tstNextSpans(spans, 7, 3, 4);
377     assertFalse("final next", spans.next());
378   }
379
380   public void testSpanOrUnused() throws Exception {
381     Spans spans = orSpans(new String[] {"w5", "unusedTerm", "yy"});
382     tstNextSpans(spans, 0, 4, 5);
383     tstNextSpans(spans, 2, 3, 4);
384     tstNextSpans(spans, 3, 4, 5);
385     tstNextSpans(spans, 7, 3, 4);
386     assertFalse("final next", spans.next());
387   }
388
389   public void testSpanOrTripleSameDoc() throws Exception {
390     Spans spans = orSpans(new String[] {"t1", "t2", "t3"});
391     tstNextSpans(spans, 11, 0, 1);
392     tstNextSpans(spans, 11, 1, 2);
393     tstNextSpans(spans, 11, 2, 3);
394     tstNextSpans(spans, 11, 3, 4);
395     tstNextSpans(spans, 11, 4, 5);
396     tstNextSpans(spans, 11, 5, 6);
397     assertFalse("final next", spans.next());
398   }
399
400   public void testSpanScorerZeroSloppyFreq() throws Exception {
401     boolean ordered = true;
402     int slop = 1;
403
404     final Similarity sim = new DefaultSimilarity() {
405       @Override
406       public float sloppyFreq(int distance) {
407         return 0.0f;
408       }
409     };
410
411     SpanNearQuery snq = new SpanNearQuery(
412                               new SpanQuery[] {
413                                 makeSpanTermQuery("t1"),
414                                 makeSpanTermQuery("t2") },
415                               slop,
416                               ordered) {
417       @Override
418       public Similarity getSimilarity(Searcher s) {
419         return sim;
420       }
421       };
422
423     Scorer spanScorer = searcher.createNormalizedWeight(snq).scorer(searcher.getIndexReader(), true, false);
424
425     assertTrue("first doc", spanScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
426     assertEquals("first doc number", spanScorer.docID(), 11);
427     float score = spanScorer.score();
428     assertTrue("first doc score should be zero, " + score, score == 0.0f);
429     assertTrue("no second doc", spanScorer.nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
430   }
431
432   // LUCENE-1404
433   private void addDoc(IndexWriter writer, String id, String text) throws IOException {
434     final Document doc = new Document();
435     doc.add( newField("id", id, Field.Store.YES, Field.Index.NOT_ANALYZED) );
436     doc.add( newField("text", text, Field.Store.YES, Field.Index.ANALYZED) );
437     writer.addDocument(doc);
438   }
439
440   // LUCENE-1404
441   private int hitCount(Searcher searcher, String word) throws Throwable {
442     return searcher.search(new TermQuery(new Term("text", word)), 10).totalHits;
443   }
444
445   // LUCENE-1404
446   private SpanQuery createSpan(String value) {
447     return new SpanTermQuery(new Term("text", value));
448   }                     
449   
450   // LUCENE-1404
451   private SpanQuery createSpan(int slop, boolean ordered, SpanQuery[] clauses) {
452     return new SpanNearQuery(clauses, slop, ordered);
453   }
454
455   // LUCENE-1404
456   private SpanQuery createSpan(int slop, boolean ordered, String term1, String term2) {
457     return createSpan(slop, ordered, new SpanQuery[] {createSpan(term1), createSpan(term2)});
458   }
459
460   // LUCENE-1404
461   public void testNPESpanQuery() throws Throwable {
462     final Directory dir = newDirectory();
463     final IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
464         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
465
466     // Add documents
467     addDoc(writer, "1", "the big dogs went running to the market");
468     addDoc(writer, "2", "the cat chased the mouse, then the cat ate the mouse quickly");
469     
470     // Commit
471     writer.close();
472
473     // Get searcher
474     final IndexReader reader = IndexReader.open(dir, true);
475     final IndexSearcher searcher = newSearcher(reader);
476
477     // Control (make sure docs indexed)
478     assertEquals(2, hitCount(searcher, "the"));
479     assertEquals(1, hitCount(searcher, "cat"));
480     assertEquals(1, hitCount(searcher, "dogs"));
481     assertEquals(0, hitCount(searcher, "rabbit"));
482
483     // This throws exception (it shouldn't)
484     assertEquals(1,
485                  searcher.search(createSpan(0, true,                                 
486                                             new SpanQuery[] {createSpan(4, false, "chased", "cat"),
487                                                              createSpan("ate")}), 10).totalHits);
488     searcher.close();
489     reader.close();
490     dir.close();
491   }
492 }