View Javadoc

1   /*
2    * Copyright 2003-2004 Michael Franken, Zilverline.
3    *
4    * The contents of this file, or the files included with this file, are subject to
5    * the current version of ZILVERLINE Collaborative Source License for the
6    * Zilverline Search Engine (the "License"); You may not use this file except in
7    * compliance with the License.
8    *
9    * You may obtain a copy of the License at
10   *
11   *     http://www.zilverline.org.
12   *
13   * See the License for the rights, obligations and
14   * limitations governing use of the contents of the file.
15   *
16   * The Original and Upgraded Code is the Zilverline Search Engine. The developer of
17   * the Original and Upgraded Code is Michael Franken. Michael Franken owns the
18   * copyrights in the portions it created. All Rights Reserved.
19   *
20   */
21  
22  package org.zilverline.lucene;
23  
24  import java.io.IOException;
25  import java.io.StringReader;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Vector;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  import org.apache.lucene.analysis.Analyzer;
34  import org.apache.lucene.analysis.TokenStream;
35  import org.apache.lucene.index.Term;
36  import org.apache.lucene.queryParser.ParseException;
37  import org.apache.lucene.queryParser.QueryParser;
38  import org.apache.lucene.search.BooleanQuery;
39  import org.apache.lucene.search.PhraseQuery;
40  import org.apache.lucene.search.Query;
41  
42  /***
43   * BoostingParser extends QueryParser by boosting its terms.
44   */
45  public class BoostingParser extends QueryParser {
46      /*** logger for Commons logging. */
47      private static Log log = LogFactory.getLog(BoostingParser.class);
48  
49      private String defaultField = "contents";
50  
51      private BoostFactor factors;
52  
53      /***
54       * @param factors The factors to set.
55       */
56      public void setFactors(BoostFactor factors) {
57          this.factors = factors;
58      }
59  
60      public BoostingParser(String f, Analyzer a) {
61          super(f, a);
62          defaultField = f;
63      }
64  
65      /***
66       * Callback that returns Query with boosted fields using BoostFactors
67       * 
68       * @param field the field to query
69       * @param analyzer the analyzer to use
70       * @param queryText the query
71       * 
72       * @return Query object
73       * 
74       * @throws ParseException if Query can't be made
75       * 
76       */
77      protected Query getFieldQuery(String field, Analyzer analyzer, String queryText) throws ParseException {
78          // Use the analyzer to get all the tokens, and then build a TermQuery,
79          // PhraseQuery, or nothing based on the term count
80          // for field that contain 'contents' add boostfactors for other terms
81          // specified in BoostFactor
82          if (factors != null && factors.getFactors() != null && !factors.getFactors().isEmpty() && defaultField.equals(field)) {
83              TokenStream source = analyzer.tokenStream(field, new StringReader(queryText));
84              Vector v = new Vector();
85              org.apache.lucene.analysis.Token t;
86  
87              while (true) {
88                  try {
89                      t = source.next();
90                  }
91                  catch (IOException e) {
92                      t = null;
93                  }
94                  if (t == null) {
95                      break;
96                  }
97                  v.addElement(t.termText());
98                  log.debug(field + " , " + t.termText());
99              }
100 
101             try {
102                 source.close();
103             }
104             catch (IOException e) {
105                 log.error("Unexpected Exception");
106             }
107 
108             if (v.size() == 0) {
109                 return null;
110             } else {
111                 // create a new composed query
112                 BooleanQuery bq = new BooleanQuery();
113 
114                 // For all boostfactors create a new PhraseQuery
115                 Iterator iter = factors.getFactors().entrySet().iterator();
116 
117                 while (iter.hasNext()) {
118                     Map.Entry element = (Map.Entry) iter.next();
119                     String thisField = ((String) element.getKey()).toLowerCase();
120                     Float boost = (Float) element.getValue();
121                     PhraseQuery q = new PhraseQuery();
122 
123                     // and add all the terms of the query
124                     for (int i = 0; i < v.size(); i++) {
125                         q.add(new Term(thisField, (String) v.elementAt(i)));
126                     }
127 
128                     // boost the query
129                     q.setBoost(boost.floatValue());
130 
131                     // and add it to the composed query
132                     bq.add(q, false, false);
133                 }
134                 log.debug("Query: " + bq);
135 
136                 return bq;
137             }
138         } else {
139             log.debug("Treat like normal query: " + queryText);
140             return super.getFieldQuery(field, analyzer, queryText);
141         }
142     }
143 
144 }