pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / queryparser / src / test / org / apache / lucene / queryParser / standard / TestMultiFieldQueryParserWrapper.java
1 package org.apache.lucene.queryParser.standard;
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 java.io.Reader;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.apache.lucene.analysis.Analyzer;
25 import org.apache.lucene.analysis.TokenStream;
26 import org.apache.lucene.analysis.standard.StandardAnalyzer;
27 import org.apache.lucene.document.Document;
28 import org.apache.lucene.document.Field;
29 import org.apache.lucene.index.IndexWriter;
30 import org.apache.lucene.queryParser.ParseException;
31 import org.apache.lucene.queryParser.standard.MultiFieldQueryParserWrapper;
32 import org.apache.lucene.queryParser.standard.QueryParserWrapper;
33 import org.apache.lucene.search.BooleanClause;
34 import org.apache.lucene.search.IndexSearcher;
35 import org.apache.lucene.search.Query;
36 import org.apache.lucene.search.ScoreDoc;
37 import org.apache.lucene.search.BooleanClause.Occur;
38 import org.apache.lucene.store.Directory;
39 import org.apache.lucene.util.LuceneTestCase;
40
41 /**
42  * Tests multi field query parsing using the
43  * {@link MultiFieldQueryParserWrapper}.
44  * 
45  * @deprecated this tests test the deprecated MultiFieldQueryParserWrapper, so
46  *             when the latter is gone, so should this test.
47  */
48 @Deprecated
49 public class TestMultiFieldQueryParserWrapper extends LuceneTestCase {
50
51   /**
52    * test stop words parsing for both the non static form, and for the
53    * corresponding static form (qtxt, fields[]).
54    */
55   public void testStopwordsParsing() throws Exception {
56     assertStopQueryEquals("one", "b:one t:one");
57     assertStopQueryEquals("one stop", "b:one t:one");
58     assertStopQueryEquals("one (stop)", "b:one t:one");
59     assertStopQueryEquals("one ((stop))", "b:one t:one");
60     assertStopQueryEquals("stop", "");
61     assertStopQueryEquals("(stop)", "");
62     assertStopQueryEquals("((stop))", "");
63   }
64
65   // verify parsing of query using a stopping analyzer
66   private void assertStopQueryEquals(String qtxt, String expectedRes)
67       throws Exception {
68     String[] fields = { "b", "t" };
69     Occur occur[] = { Occur.SHOULD, Occur.SHOULD };
70     TestQueryParserWrapper.QPTestAnalyzer a = new TestQueryParserWrapper.QPTestAnalyzer();
71     MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
72         fields, a);
73
74     Query q = mfqp.parse(qtxt);
75     assertEquals(expectedRes, q.toString());
76
77     q = MultiFieldQueryParserWrapper.parse(qtxt, fields, occur, a);
78     assertEquals(expectedRes, q.toString());
79   }
80
81   public void testSimple() throws Exception {
82     String[] fields = { "b", "t" };
83     MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
84         fields, new StandardAnalyzer(TEST_VERSION_CURRENT));
85
86     Query q = mfqp.parse("one");
87     assertEquals("b:one t:one", q.toString());
88
89     q = mfqp.parse("one two");
90     assertEquals("(b:one t:one) (b:two t:two)", q.toString());
91
92     q = mfqp.parse("+one +two");
93     assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
94
95     q = mfqp.parse("+one -two -three");
96     assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q
97         .toString());
98
99     q = mfqp.parse("one^2 two");
100     assertEquals("((b:one t:one)^2.0) (b:two t:two)", q.toString());
101
102     q = mfqp.parse("one~ two");
103     assertEquals("(b:one~0.5 t:one~0.5) (b:two t:two)", q.toString());
104
105     q = mfqp.parse("one~0.8 two^2");
106     assertEquals("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)", q.toString());
107
108     q = mfqp.parse("one* two*");
109     assertEquals("(b:one* t:one*) (b:two* t:two*)", q.toString());
110
111     q = mfqp.parse("[a TO c] two");
112     assertEquals("(b:[a TO c] t:[a TO c]) (b:two t:two)", q.toString());
113
114     q = mfqp.parse("w?ldcard");
115     assertEquals("b:w?ldcard t:w?ldcard", q.toString());
116
117     q = mfqp.parse("\"foo bar\"");
118     assertEquals("b:\"foo bar\" t:\"foo bar\"", q.toString());
119
120     q = mfqp.parse("\"aa bb cc\" \"dd ee\"");
121     assertEquals("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")", q
122         .toString());
123
124     q = mfqp.parse("\"foo bar\"~4");
125     assertEquals("b:\"foo bar\"~4 t:\"foo bar\"~4", q.toString());
126
127     // LUCENE-1213: MultiFieldQueryParserWrapper was ignoring slop when phrase
128     // had a field.
129     q = mfqp.parse("b:\"foo bar\"~4");
130     assertEquals("b:\"foo bar\"~4", q.toString());
131
132     // make sure that terms which have a field are not touched:
133     q = mfqp.parse("one f:two");
134     assertEquals("(b:one t:one) f:two", q.toString());
135
136     // AND mode:
137     mfqp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
138     q = mfqp.parse("one two");
139     assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
140     q = mfqp.parse("\"aa bb cc\" \"dd ee\"");
141     assertEquals("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")",
142         q.toString());
143
144   }
145
146   public void testBoostsSimple() throws Exception {
147     Map<String,Float> boosts = new HashMap<String,Float>();
148     boosts.put("b", Float.valueOf(5));
149     boosts.put("t", Float.valueOf(10));
150     String[] fields = { "b", "t" };
151     MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
152         fields, new StandardAnalyzer(TEST_VERSION_CURRENT), boosts);
153
154     // Check for simple
155     Query q = mfqp.parse("one");
156     assertEquals("b:one^5.0 t:one^10.0", q.toString());
157
158     // Check for AND
159     q = mfqp.parse("one AND two");
160     assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0)", q
161         .toString());
162
163     // Check for OR
164     q = mfqp.parse("one OR two");
165     assertEquals("(b:one^5.0 t:one^10.0) (b:two^5.0 t:two^10.0)", q.toString());
166
167     // Check for AND and a field
168     q = mfqp.parse("one AND two AND foo:test");
169     assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0) +foo:test", q
170         .toString());
171
172     q = mfqp.parse("one^3 AND two^4");
173     assertEquals("+((b:one^5.0 t:one^10.0)^3.0) +((b:two^5.0 t:two^10.0)^4.0)",
174         q.toString());
175   }
176
177   public void testStaticMethod1() throws ParseException {
178     String[] fields = { "b", "t" };
179     String[] queries = { "one", "two" };
180     Query q = MultiFieldQueryParserWrapper.parse(queries, fields,
181         new StandardAnalyzer(TEST_VERSION_CURRENT));
182     assertEquals("b:one t:two", q.toString());
183
184     String[] queries2 = { "+one", "+two" };
185     q = MultiFieldQueryParserWrapper.parse(queries2, fields,
186         new StandardAnalyzer(TEST_VERSION_CURRENT));
187     assertEquals("(+b:one) (+t:two)", q.toString());
188
189     String[] queries3 = { "one", "+two" };
190     q = MultiFieldQueryParserWrapper.parse(queries3, fields,
191         new StandardAnalyzer(TEST_VERSION_CURRENT));
192     assertEquals("b:one (+t:two)", q.toString());
193
194     String[] queries4 = { "one +more", "+two" };
195     q = MultiFieldQueryParserWrapper.parse(queries4, fields,
196         new StandardAnalyzer(TEST_VERSION_CURRENT));
197     assertEquals("(b:one +b:more) (+t:two)", q.toString());
198
199     String[] queries5 = { "blah" };
200     try {
201       q = MultiFieldQueryParserWrapper.parse(queries5, fields,
202           new StandardAnalyzer(TEST_VERSION_CURRENT));
203       fail();
204     } catch (IllegalArgumentException e) {
205       // expected exception, array length differs
206     }
207
208     // check also with stop words for this static form (qtxts[], fields[]).
209     TestQueryParserWrapper.QPTestAnalyzer stopA = new TestQueryParserWrapper.QPTestAnalyzer();
210
211     String[] queries6 = { "((+stop))", "+((stop))" };
212     q = MultiFieldQueryParserWrapper.parse(queries6, fields, stopA);
213     assertEquals("", q.toString());
214
215     String[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" };
216     q = MultiFieldQueryParserWrapper.parse(queries7, fields, stopA);
217     assertEquals("(b:one +b:more) (+t:two)", q.toString());
218
219   }
220
221   public void testStaticMethod2() throws ParseException {
222     String[] fields = { "b", "t" };
223     BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
224         BooleanClause.Occur.MUST_NOT };
225     Query q = MultiFieldQueryParserWrapper.parse("one", fields, flags,
226         new StandardAnalyzer(TEST_VERSION_CURRENT));
227     assertEquals("+b:one -t:one", q.toString());
228
229     q = MultiFieldQueryParserWrapper.parse("one two", fields, flags,
230         new StandardAnalyzer(TEST_VERSION_CURRENT));
231     assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
232
233     try {
234       BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
235       q = MultiFieldQueryParserWrapper.parse("blah", fields, flags2,
236           new StandardAnalyzer(TEST_VERSION_CURRENT));
237       fail();
238     } catch (IllegalArgumentException e) {
239       // expected exception, array length differs
240     }
241   }
242
243   public void testStaticMethod2Old() throws ParseException {
244     String[] fields = { "b", "t" };
245     // int[] flags = {MultiFieldQueryParserWrapper.REQUIRED_FIELD,
246     // MultiFieldQueryParserWrapper.PROHIBITED_FIELD};
247     BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
248         BooleanClause.Occur.MUST_NOT };
249
250     Query q = MultiFieldQueryParserWrapper.parse("one", fields, flags,
251         new StandardAnalyzer(TEST_VERSION_CURRENT));// , fields, flags, new StandardAnalyzer());
252     assertEquals("+b:one -t:one", q.toString());
253
254     q = MultiFieldQueryParserWrapper.parse("one two", fields, flags,
255         new StandardAnalyzer(TEST_VERSION_CURRENT));
256     assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
257
258     try {
259       BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
260       q = MultiFieldQueryParserWrapper.parse("blah", fields, flags2,
261           new StandardAnalyzer(TEST_VERSION_CURRENT));
262       fail();
263     } catch (IllegalArgumentException e) {
264       // expected exception, array length differs
265     }
266   }
267
268   public void testStaticMethod3() throws ParseException {
269     String[] queries = { "one", "two", "three" };
270     String[] fields = { "f1", "f2", "f3" };
271     BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
272         BooleanClause.Occur.MUST_NOT, BooleanClause.Occur.SHOULD };
273     Query q = MultiFieldQueryParserWrapper.parse(queries, fields, flags,
274         new StandardAnalyzer(TEST_VERSION_CURRENT));
275     assertEquals("+f1:one -f2:two f3:three", q.toString());
276
277     try {
278       BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
279       q = MultiFieldQueryParserWrapper.parse(queries, fields, flags2,
280           new StandardAnalyzer(TEST_VERSION_CURRENT));
281       fail();
282     } catch (IllegalArgumentException e) {
283       // expected exception, array length differs
284     }
285   }
286
287   public void testStaticMethod3Old() throws ParseException {
288     String[] queries = { "one", "two" };
289     String[] fields = { "b", "t" };
290     BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
291         BooleanClause.Occur.MUST_NOT };
292     Query q = MultiFieldQueryParserWrapper.parse(queries, fields, flags,
293         new StandardAnalyzer(TEST_VERSION_CURRENT));
294     assertEquals("+b:one -t:two", q.toString());
295
296     try {
297       BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
298       q = MultiFieldQueryParserWrapper.parse(queries, fields, flags2,
299           new StandardAnalyzer(TEST_VERSION_CURRENT));
300       fail();
301     } catch (IllegalArgumentException e) {
302       // expected exception, array length differs
303     }
304   }
305
306   public void testAnalyzerReturningNull() throws ParseException {
307     String[] fields = new String[] { "f1", "f2", "f3" };
308     MultiFieldQueryParserWrapper parser = new MultiFieldQueryParserWrapper(
309         fields, new AnalyzerReturningNull());
310     Query q = parser.parse("bla AND blo");
311     assertEquals("+(f2:bla f3:bla) +(f2:blo f3:blo)", q.toString());
312     // the following queries are not affected as their terms are not analyzed
313     // anyway:
314     q = parser.parse("bla*");
315     assertEquals("f1:bla* f2:bla* f3:bla*", q.toString());
316     q = parser.parse("bla~");
317     assertEquals("f1:bla~0.5 f2:bla~0.5 f3:bla~0.5", q.toString());
318     q = parser.parse("[a TO c]");
319     assertEquals("f1:[a TO c] f2:[a TO c] f3:[a TO c]", q.toString());
320   }
321
322   public void testStopWordSearching() throws Exception {
323     Analyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
324     Directory ramDir = newDirectory();
325     IndexWriter iw = new IndexWriter(ramDir, analyzer, true,
326         IndexWriter.MaxFieldLength.LIMITED);
327     Document doc = new Document();
328     doc.add(newField("body", "blah the footest blah", Field.Store.NO,
329         Field.Index.ANALYZED));
330     iw.addDocument(doc);
331     iw.close();
332
333     MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
334         new String[] { "body" }, analyzer);
335     mfqp.setDefaultOperator(QueryParserWrapper.Operator.AND);
336     Query q = mfqp.parse("the footest");
337     IndexSearcher is = new IndexSearcher(ramDir, true);
338     ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
339     assertEquals(1, hits.length);
340     is.close();
341     ramDir.close();
342   }
343
344   /**
345    * Return empty tokens for field "f1".
346    */
347   private static class AnalyzerReturningNull extends Analyzer {
348     StandardAnalyzer stdAnalyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
349
350     public AnalyzerReturningNull() {
351     }
352
353     @Override
354     public TokenStream tokenStream(String fieldName, Reader reader) {
355       if ("f1".equals(fieldName)) {
356         return new EmptyTokenStream();
357       } else {
358         return stdAnalyzer.tokenStream(fieldName, reader);
359       }
360     }
361
362     private static class EmptyTokenStream extends TokenStream {
363       @Override
364       public boolean incrementToken() {
365         return false;
366       }
367     }
368   }
369
370 }