KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > lucene > queryParser > MultiFieldQueryParser


1 package org.apache.lucene.queryParser;
2
3 /**
4  * Copyright 2004 The Apache Software Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.util.Vector JavaDoc;
20
21 import org.apache.lucene.analysis.Analyzer;
22 import org.apache.lucene.search.BooleanClause;
23 import org.apache.lucene.search.BooleanQuery;
24 import org.apache.lucene.search.MultiPhraseQuery;
25 import org.apache.lucene.search.PhraseQuery;
26 import org.apache.lucene.search.Query;
27
28 /**
29  * A QueryParser which constructs queries to search multiple fields.
30  *
31  * @author <a HREF="mailto:kelvin@relevanz.com">Kelvin Tan</a>, Daniel Naber
32  * @version $Revision: 295117 $
33  */

34 public class MultiFieldQueryParser extends QueryParser
35 {
36   
37   private String JavaDoc[] fields;
38
39   /**
40    * Creates a MultiFieldQueryParser.
41    *
42    * <p>It will, when parse(String query)
43    * is called, construct a query like this (assuming the query consists of
44    * two terms and you specify the two fields <code>title</code> and <code>body</code>):</p>
45    *
46    * <code>
47    * (title:term1 body:term1) (title:term2 body:term2)
48    * </code>
49    *
50    * <p>When setDefaultOperator(AND_OPERATOR) is set, the result will be:</p>
51    *
52    * <code>
53    * +(title:term1 body:term1) +(title:term2 body:term2)
54    * </code>
55    *
56    * <p>In other words, all the query's terms must appear, but it doesn't matter in
57    * what fields they appear.</p>
58    */

59   public MultiFieldQueryParser(String JavaDoc[] fields, Analyzer analyzer) {
60     super(null, analyzer);
61     this.fields = fields;
62   }
63   
64   protected Query getFieldQuery(String JavaDoc field, String JavaDoc queryText, int slop) throws ParseException {
65     if (field == null) {
66       Vector JavaDoc clauses = new Vector JavaDoc();
67       for (int i = 0; i < fields.length; i++) {
68         Query q = super.getFieldQuery(fields[i], queryText);
69         if (q != null) {
70           if (q instanceof PhraseQuery) {
71             ((PhraseQuery) q).setSlop(slop);
72           }
73           if (q instanceof MultiPhraseQuery) {
74             ((MultiPhraseQuery) q).setSlop(slop);
75           }
76           clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
77         }
78       }
79       if (clauses.size() == 0) // happens for stopwords
80
return null;
81       return getBooleanQuery(clauses, true);
82     }
83     return super.getFieldQuery(field, queryText);
84   }
85   
86
87   protected Query getFieldQuery(String JavaDoc field, String JavaDoc queryText) throws ParseException {
88     return getFieldQuery(field, queryText, 0);
89   }
90   
91   /**
92    * @deprecated use {@link #getFieldQuery(String, String)}
93    */

94   protected Query getFieldQuery(String JavaDoc field, Analyzer analyzer, String JavaDoc queryText)
95       throws ParseException {
96     return getFieldQuery(field, queryText);
97   }
98   
99   /**
100    * @deprecated use {@link #getFuzzyQuery(String, String, float)}
101    */

102   protected Query getFuzzyQuery(String JavaDoc field, String JavaDoc termStr) throws ParseException {
103     return getFuzzyQuery(field, termStr, fuzzyMinSim);
104   }
105
106   protected Query getFuzzyQuery(String JavaDoc field, String JavaDoc termStr, float minSimilarity) throws ParseException
107   {
108     if (field == null) {
109       Vector JavaDoc clauses = new Vector JavaDoc();
110       for (int i = 0; i < fields.length; i++) {
111         clauses.add(new BooleanClause(super.getFuzzyQuery(fields[i], termStr, minSimilarity),
112             BooleanClause.Occur.SHOULD));
113       }
114       return getBooleanQuery(clauses, true);
115     }
116     return super.getFuzzyQuery(field, termStr, minSimilarity);
117   }
118
119   protected Query getPrefixQuery(String JavaDoc field, String JavaDoc termStr) throws ParseException
120   {
121     if (field == null) {
122       Vector JavaDoc clauses = new Vector JavaDoc();
123       for (int i = 0; i < fields.length; i++) {
124         clauses.add(new BooleanClause(super.getPrefixQuery(fields[i], termStr),
125             BooleanClause.Occur.SHOULD));
126       }
127       return getBooleanQuery(clauses, true);
128     }
129     return super.getPrefixQuery(field, termStr);
130   }
131
132   protected Query getWildcardQuery(String JavaDoc field, String JavaDoc termStr) throws ParseException {
133     if (field == null) {
134       Vector JavaDoc clauses = new Vector JavaDoc();
135       for (int i = 0; i < fields.length; i++) {
136         clauses.add(new BooleanClause(super.getWildcardQuery(fields[i], termStr),
137             BooleanClause.Occur.SHOULD));
138       }
139       return getBooleanQuery(clauses, true);
140     }
141     return super.getWildcardQuery(field, termStr);
142   }
143   
144   /** @throws ParseException
145    * @deprecated use {@link #getRangeQuery(String, String, String, boolean)}
146   */

147   protected Query getRangeQuery(String JavaDoc field, Analyzer analyzer,
148       String JavaDoc part1, String JavaDoc part2, boolean inclusive) throws ParseException {
149    return getRangeQuery(field, part1, part2, inclusive);
150   }
151  
152   protected Query getRangeQuery(String JavaDoc field, String JavaDoc part1, String JavaDoc part2, boolean inclusive) throws ParseException {
153     if (field == null) {
154       Vector JavaDoc clauses = new Vector JavaDoc();
155       for (int i = 0; i < fields.length; i++) {
156         clauses.add(new BooleanClause(super.getRangeQuery(fields[i], part1, part2, inclusive),
157             BooleanClause.Occur.SHOULD));
158       }
159       return getBooleanQuery(clauses, true);
160     }
161     return super.getRangeQuery(field, part1, part2, inclusive);
162   }
163  
164
165   /** @deprecated */
166   public static final int NORMAL_FIELD = 0;
167   /** @deprecated */
168   public static final int REQUIRED_FIELD = 1;
169   /** @deprecated */
170   public static final int PROHIBITED_FIELD = 2;
171
172   /**
173    * @deprecated use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
174    */

175   public MultiFieldQueryParser(QueryParserTokenManager tm)
176   {
177     super(tm);
178   }
179
180   /**
181    * @deprecated use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
182    */

183   public MultiFieldQueryParser(CharStream stream)
184   {
185     super(stream);
186   }
187
188   /**
189    * @deprecated use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
190    */

191   public MultiFieldQueryParser(String JavaDoc f, Analyzer a)
192   {
193     super(f, a);
194   }
195
196   /**
197    * Parses a query which searches on the fields specified.
198    * If x fields are specified, this effectively constructs:
199    *
200    * <code>
201    * (field1:query) (field2:query) (field3:query)...(fieldx:query)
202    * </code>
203    *
204    * @param query Query string to parse
205    * @param fields Fields to search on
206    * @param analyzer Analyzer to use
207    * @throws ParseException if query parsing fails
208    * @throws TokenMgrError if query parsing fails
209    * @deprecated use {@link #parse(String)} instead but note that it
210    * returns a different query for queries where all terms are required:
211    * its query excepts all terms, no matter in what field they occur whereas
212    * the query built by this (deprecated) method expected all terms in all fields
213    * at the same time.
214    */

215   public static Query parse(String JavaDoc query, String JavaDoc[] fields, Analyzer analyzer)
216     throws ParseException
217   {
218     BooleanQuery bQuery = new BooleanQuery();
219     for (int i = 0; i < fields.length; i++)
220     {
221       Query q = parse(query, fields[i], analyzer);
222       bQuery.add(q, BooleanClause.Occur.SHOULD);
223     }
224     return bQuery;
225   }
226
227   /**
228    * Parses a query which searches on the fields specified.
229    * <p>
230    * If x fields are specified, this effectively constructs:
231    * <pre>
232    * <code>
233    * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
234    * </code>
235    * </pre>
236    * @param queries Queries strings to parse
237    * @param fields Fields to search on
238    * @param analyzer Analyzer to use
239    * @throws ParseException if query parsing fails
240    * @throws TokenMgrError if query parsing fails
241    * @throws IllegalArgumentException if the length of the queries array differs
242    * from the length of the fields array
243    */

244   public static Query parse(String JavaDoc[] queries, String JavaDoc[] fields,
245       Analyzer analyzer) throws ParseException
246   {
247     if (queries.length != fields.length)
248       throw new IllegalArgumentException JavaDoc("queries.length != fields.length");
249     BooleanQuery bQuery = new BooleanQuery();
250     for (int i = 0; i < fields.length; i++)
251     {
252       QueryParser qp = new QueryParser(fields[i], analyzer);
253       Query q = qp.parse(queries[i]);
254       bQuery.add(q, BooleanClause.Occur.SHOULD);
255     }
256     return bQuery;
257   }
258
259   /**
260    * Parses a query, searching on the fields specified.
261    * Use this if you need to specify certain fields as required,
262    * and others as prohibited.
263    * <p><pre>
264    * Usage:
265    * <code>
266    * String[] fields = {"filename", "contents", "description"};
267    * int[] flags = {MultiFieldQueryParser.NORMAL_FIELD,
268    * MultiFieldQueryParser.REQUIRED_FIELD,
269    * MultiFieldQueryParser.PROHIBITED_FIELD,};
270    * parse(query, fields, flags, analyzer);
271    * </code>
272    * </pre>
273    *<p>
274    * The code above would construct a query:
275    * <pre>
276    * <code>
277    * (filename:query) +(contents:query) -(description:query)
278    * </code>
279    * </pre>
280    *
281    * @param query Query string to parse
282    * @param fields Fields to search on
283    * @param flags Flags describing the fields
284    * @param analyzer Analyzer to use
285    * @throws ParseException if query parsing fails
286    * @throws TokenMgrError if query parsing fails
287    * @throws IllegalArgumentException if the length of the fields array differs
288    * from the length of the flags array
289    * @deprecated use {@link #parse(String, String[], BooleanClause.Occur[], Analyzer)} instead
290    */

291   public static Query parse(String JavaDoc query, String JavaDoc[] fields, int[] flags,
292     Analyzer analyzer) throws ParseException
293   {
294     if (fields.length != flags.length)
295       throw new IllegalArgumentException JavaDoc("fields.length != flags.length");
296     BooleanQuery bQuery = new BooleanQuery();
297     for (int i = 0; i < fields.length; i++)
298     {
299       QueryParser qp = new QueryParser(fields[i], analyzer);
300       Query q = qp.parse(query);
301       int flag = flags[i];
302       switch (flag)
303       {
304         case REQUIRED_FIELD:
305           bQuery.add(q, BooleanClause.Occur.MUST);
306           break;
307         case PROHIBITED_FIELD:
308           bQuery.add(q, BooleanClause.Occur.MUST_NOT);
309           break;
310         default:
311           bQuery.add(q, BooleanClause.Occur.SHOULD);
312         break;
313       }
314     }
315     return bQuery;
316   }
317
318   /**
319    * Parses a query, searching on the fields specified.
320    * Use this if you need to specify certain fields as required,
321    * and others as prohibited.
322    * <p><pre>
323    * Usage:
324    * <code>
325    * String[] fields = {"filename", "contents", "description"};
326    * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
327    * BooleanClause.Occur.MUST,
328    * BooleanClause.Occur.MUST_NOT};
329    * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
330    * </code>
331    * </pre>
332    *<p>
333    * The code above would construct a query:
334    * <pre>
335    * <code>
336    * (filename:query) +(contents:query) -(description:query)
337    * </code>
338    * </pre>
339    *
340    * @param query Query string to parse
341    * @param fields Fields to search on
342    * @param flags Flags describing the fields
343    * @param analyzer Analyzer to use
344    * @throws ParseException if query parsing fails
345    * @throws TokenMgrError if query parsing fails
346    * @throws IllegalArgumentException if the length of the fields array differs
347    * from the length of the flags array
348    */

349   public static Query parse(String JavaDoc query, String JavaDoc[] fields,
350       BooleanClause.Occur[] flags, Analyzer analyzer) throws ParseException {
351     if (fields.length != flags.length)
352       throw new IllegalArgumentException JavaDoc("fields.length != flags.length");
353     BooleanQuery bQuery = new BooleanQuery();
354     for (int i = 0; i < fields.length; i++) {
355       QueryParser qp = new QueryParser(fields[i], analyzer);
356       Query q = qp.parse(query);
357       bQuery.add(q, flags[i]);
358     }
359     return bQuery;
360   }
361
362   /**
363    * Parses a query, searching on the fields specified. Use this if you need to
364    * specify certain fields as required, and others as prohibited.
365    * <p>
366    * <pre>
367    * Usage:
368    * <code>
369    * String[] fields = { &quot;filename&quot;, &quot;contents&quot;, &quot;description&quot; };
370    * int[] flags = { MultiFieldQueryParser.NORMAL_FIELD,
371    * MultiFieldQueryParser.REQUIRED_FIELD,
372    * MultiFieldQueryParser.PROHIBITED_FIELD, };
373    * parse(query, fields, flags, analyzer);
374    * </code>
375    * </pre>
376    *
377    * <p>
378    * The code above would construct a query:
379    * <pre>
380    * <code>
381    * (filename:query1) +(contents:query2) -(description:query3)
382    * </code>
383    * </pre>
384    *
385    * @param queries Queries string to parse
386    * @param fields Fields to search on
387    * @param flags Flags describing the fields
388    * @param analyzer Analyzer to use
389    * @throws ParseException if query parsing fails
390    * @throws TokenMgrError if query parsing fails
391    * @throws IllegalArgumentException if the length of the queries, fields, and flags array differ
392    * @deprecated use {@link #parse(String[], String[], BooleanClause.Occur[], Analyzer)} instead
393    */

394   public static Query parse(String JavaDoc[] queries, String JavaDoc[] fields, int[] flags,
395       Analyzer analyzer) throws ParseException
396   {
397     if (!(queries.length == fields.length && queries.length == flags.length))
398       throw new IllegalArgumentException JavaDoc("queries, fields, and flags array have have different length");
399     BooleanQuery bQuery = new BooleanQuery();
400     for (int i = 0; i < fields.length; i++)
401     {
402       QueryParser qp = new QueryParser(fields[i], analyzer);
403       Query q = qp.parse(queries[i]);
404       int flag = flags[i];
405       switch (flag)
406       {
407         case REQUIRED_FIELD:
408           bQuery.add(q, BooleanClause.Occur.MUST);
409           break;
410         case PROHIBITED_FIELD:
411           bQuery.add(q, BooleanClause.Occur.MUST_NOT);
412           break;
413         default:
414           bQuery.add(q, BooleanClause.Occur.SHOULD);
415           break;
416       }
417     }
418     return bQuery;
419   }
420
421   /**
422    * Parses a query, searching on the fields specified.
423    * Use this if you need to specify certain fields as required,
424    * and others as prohibited.
425    * <p><pre>
426    * Usage:
427    * <code>
428    * String[] query = {"query1", "query2", "query3"};
429    * String[] fields = {"filename", "contents", "description"};
430    * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
431    * BooleanClause.Occur.MUST,
432    * BooleanClause.Occur.MUST_NOT};
433    * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
434    * </code>
435    * </pre>
436    *<p>
437    * The code above would construct a query:
438    * <pre>
439    * <code>
440    * (filename:query1) +(contents:query2) -(description:query3)
441    * </code>
442    * </pre>
443    *
444    * @param queries Queries string to parse
445    * @param fields Fields to search on
446    * @param flags Flags describing the fields
447    * @param analyzer Analyzer to use
448    * @throws ParseException if query parsing fails
449    * @throws TokenMgrError if query parsing fails
450    * @throws IllegalArgumentException if the length of the queries, fields,
451    * and flags array differ
452    */

453   public static Query parse(String JavaDoc[] queries, String JavaDoc[] fields, BooleanClause.Occur[] flags,
454       Analyzer analyzer) throws ParseException
455   {
456     if (!(queries.length == fields.length && queries.length == flags.length))
457       throw new IllegalArgumentException JavaDoc("queries, fields, and flags array have have different length");
458     BooleanQuery bQuery = new BooleanQuery();
459     for (int i = 0; i < fields.length; i++)
460     {
461       QueryParser qp = new QueryParser(fields[i], analyzer);
462       Query q = qp.parse(queries[i]);
463       bQuery.add(q, flags[i]);
464     }
465     return bQuery;
466   }
467
468 }
469
Popular Tags