1 package org.apache.lucene.search; 2 3 18 19 import java.io.IOException ; 20 import java.util.ArrayList ; 21 import java.util.Iterator ; 22 import java.util.Vector ; 23 24 import org.apache.lucene.index.IndexReader; 25 import org.apache.lucene.index.MultipleTermPositions; 26 import org.apache.lucene.index.Term; 27 import org.apache.lucene.index.TermPositions; 28 import org.apache.lucene.search.Query; 29 import org.apache.lucene.util.ToStringUtils; 30 31 42 public class MultiPhraseQuery extends Query { 43 private String field; 44 private ArrayList termArrays = new ArrayList (); 45 private Vector positions = new Vector (); 46 47 private int slop = 0; 48 49 52 public void setSlop(int s) { slop = s; } 53 54 57 public int getSlop() { return slop; } 58 59 62 public void add(Term term) { add(new Term[]{term}); } 63 64 69 public void add(Term[] terms) { 70 int position = 0; 71 if (positions.size() > 0) 72 position = ((Integer ) positions.lastElement()).intValue() + 1; 73 74 add(terms, position); 75 } 76 77 84 public void add(Term[] terms, int position) { 85 if (termArrays.size() == 0) 86 field = terms[0].field(); 87 88 for (int i = 0; i < terms.length; i++) { 89 if (terms[i].field() != field) { 90 throw new IllegalArgumentException ( 91 "All phrase terms must be in the same field (" + field + "): " 92 + terms[i]); 93 } 94 } 95 96 termArrays.add(terms); 97 positions.addElement(new Integer (position)); 98 } 99 100 103 public int[] getPositions() { 104 int[] result = new int[positions.size()]; 105 for (int i = 0; i < positions.size(); i++) 106 result[i] = ((Integer ) positions.elementAt(i)).intValue(); 107 return result; 108 } 109 110 private class MultiPhraseWeight implements Weight { 111 private Similarity similarity; 112 private float value; 113 private float idf; 114 private float queryNorm; 115 private float queryWeight; 116 117 public MultiPhraseWeight(Searcher searcher) 118 throws IOException { 119 this.similarity = getSimilarity(searcher); 120 121 Iterator i = termArrays.iterator(); 123 while (i.hasNext()) { 124 Term[] terms = (Term[])i.next(); 125 for (int j=0; j<terms.length; j++) { 126 idf += getSimilarity(searcher).idf(terms[j], searcher); 127 } 128 } 129 } 130 131 public Query getQuery() { return MultiPhraseQuery.this; } 132 public float getValue() { return value; } 133 134 public float sumOfSquaredWeights() { 135 queryWeight = idf * getBoost(); return queryWeight * queryWeight; } 138 139 public void normalize(float queryNorm) { 140 this.queryNorm = queryNorm; 141 queryWeight *= queryNorm; value = queryWeight * idf; } 144 145 public Scorer scorer(IndexReader reader) throws IOException { 146 if (termArrays.size() == 0) return null; 148 149 TermPositions[] tps = new TermPositions[termArrays.size()]; 150 for (int i=0; i<tps.length; i++) { 151 Term[] terms = (Term[])termArrays.get(i); 152 153 TermPositions p; 154 if (terms.length > 1) 155 p = new MultipleTermPositions(reader, terms); 156 else 157 p = reader.termPositions(terms[0]); 158 159 if (p == null) 160 return null; 161 162 tps[i] = p; 163 } 164 165 if (slop == 0) 166 return new ExactPhraseScorer(this, tps, getPositions(), similarity, 167 reader.norms(field)); 168 else 169 return new SloppyPhraseScorer(this, tps, getPositions(), similarity, 170 slop, reader.norms(field)); 171 } 172 173 public Explanation explain(IndexReader reader, int doc) 174 throws IOException { 175 Explanation result = new Explanation(); 176 result.setDescription("weight("+getQuery()+" in "+doc+"), product of:"); 177 178 Explanation idfExpl = new Explanation(idf, "idf("+getQuery()+")"); 179 180 Explanation queryExpl = new Explanation(); 182 queryExpl.setDescription("queryWeight(" + getQuery() + "), product of:"); 183 184 Explanation boostExpl = new Explanation(getBoost(), "boost"); 185 if (getBoost() != 1.0f) 186 queryExpl.addDetail(boostExpl); 187 188 queryExpl.addDetail(idfExpl); 189 190 Explanation queryNormExpl = new Explanation(queryNorm,"queryNorm"); 191 queryExpl.addDetail(queryNormExpl); 192 193 queryExpl.setValue(boostExpl.getValue() * 194 idfExpl.getValue() * 195 queryNormExpl.getValue()); 196 197 result.addDetail(queryExpl); 198 199 Explanation fieldExpl = new Explanation(); 201 fieldExpl.setDescription("fieldWeight("+getQuery()+" in "+doc+ 202 "), product of:"); 203 204 Explanation tfExpl = scorer(reader).explain(doc); 205 fieldExpl.addDetail(tfExpl); 206 fieldExpl.addDetail(idfExpl); 207 208 Explanation fieldNormExpl = new Explanation(); 209 byte[] fieldNorms = reader.norms(field); 210 float fieldNorm = 211 fieldNorms!=null ? Similarity.decodeNorm(fieldNorms[doc]) : 0.0f; 212 fieldNormExpl.setValue(fieldNorm); 213 fieldNormExpl.setDescription("fieldNorm(field="+field+", doc="+doc+")"); 214 fieldExpl.addDetail(fieldNormExpl); 215 216 fieldExpl.setValue(tfExpl.getValue() * 217 idfExpl.getValue() * 218 fieldNormExpl.getValue()); 219 220 result.addDetail(fieldExpl); 221 222 result.setValue(queryExpl.getValue() * fieldExpl.getValue()); 224 225 if (queryExpl.getValue() == 1.0f) 226 return fieldExpl; 227 228 return result; 229 } 230 } 231 232 public Query rewrite(IndexReader reader) { 233 if (termArrays.size() == 1) { Term[] terms = (Term[])termArrays.get(0); 235 BooleanQuery boq = new BooleanQuery(true); 236 for (int i=0; i<terms.length; i++) { 237 boq.add(new TermQuery(terms[i]), BooleanClause.Occur.SHOULD); 238 } 239 boq.setBoost(getBoost()); 240 return boq; 241 } else { 242 return this; 243 } 244 } 245 246 protected Weight createWeight(Searcher searcher) throws IOException { 247 return new MultiPhraseWeight(searcher); 248 } 249 250 251 public final String toString(String f) { 252 StringBuffer buffer = new StringBuffer (); 253 if (!field.equals(f)) { 254 buffer.append(field); 255 buffer.append(":"); 256 } 257 258 buffer.append("\""); 259 Iterator i = termArrays.iterator(); 260 while (i.hasNext()) { 261 Term[] terms = (Term[])i.next(); 262 if (terms.length > 1) { 263 buffer.append("("); 264 for (int j = 0; j < terms.length; j++) { 265 buffer.append(terms[j].text()); 266 if (j < terms.length-1) 267 buffer.append(" "); 268 } 269 buffer.append(")"); 270 } else { 271 buffer.append(terms[0].text()); 272 } 273 if (i.hasNext()) 274 buffer.append(" "); 275 } 276 buffer.append("\""); 277 278 if (slop != 0) { 279 buffer.append("~"); 280 buffer.append(slop); 281 } 282 283 buffer.append(ToStringUtils.boost(getBoost())); 284 285 return buffer.toString(); 286 } 287 288 289 290 public boolean equals(Object o) { 291 if (!(o instanceof MultiPhraseQuery)) return false; 292 MultiPhraseQuery other = (MultiPhraseQuery)o; 293 return this.getBoost() == other.getBoost() 294 && this.slop == other.slop 295 && this.termArrays.equals(other.termArrays) 296 && this.positions.equals(other.positions); 297 } 298 299 300 public int hashCode() { 301 return Float.floatToIntBits(getBoost()) 302 ^ slop 303 ^ termArrays.hashCode() 304 ^ positions.hashCode() 305 ^ 0x4AC65113; 306 } 307 } 308 | Popular Tags |