1 package org.apache.lucene.search; 2 3 18 19 import java.io.IOException ; 20 import java.util.Set ; 21 import java.util.Vector ; 22 23 import org.apache.lucene.index.Term; 24 import org.apache.lucene.index.TermPositions; 25 import org.apache.lucene.index.IndexReader; 26 import org.apache.lucene.util.ToStringUtils; 27 28 33 public class PhraseQuery extends Query { 34 private String field; 35 private Vector terms = new Vector (); 36 private Vector positions = new Vector (); 37 private int slop = 0; 38 39 40 public PhraseQuery() {} 41 42 56 public void setSlop(int s) { slop = s; } 57 58 public int getSlop() { return slop; } 59 60 64 public void add(Term term) { 65 int position = 0; 66 if(positions.size() > 0) 67 position = ((Integer ) positions.lastElement()).intValue() + 1; 68 69 add(term, position); 70 } 71 72 81 public void add(Term term, int position) { 82 if (terms.size() == 0) 83 field = term.field(); 84 else if (term.field() != field) 85 throw new IllegalArgumentException ("All phrase terms must be in the same field: " + term); 86 87 terms.addElement(term); 88 positions.addElement(new Integer (position)); 89 } 90 91 92 public Term[] getTerms() { 93 return (Term[])terms.toArray(new Term[0]); 94 } 95 96 99 public int[] getPositions() { 100 int[] result = new int[positions.size()]; 101 for(int i = 0; i < positions.size(); i++) 102 result[i] = ((Integer ) positions.elementAt(i)).intValue(); 103 return result; 104 } 105 106 private class PhraseWeight implements Weight { 107 private Similarity similarity; 108 private float value; 109 private float idf; 110 private float queryNorm; 111 private float queryWeight; 112 113 public PhraseWeight(Searcher searcher) 114 throws IOException { 115 this.similarity = getSimilarity(searcher); 116 117 idf = similarity.idf(terms, searcher); 118 } 119 120 public String toString() { return "weight(" + PhraseQuery.this + ")"; } 121 122 public Query getQuery() { return PhraseQuery.this; } 123 public float getValue() { return value; } 124 125 public float sumOfSquaredWeights() { 126 queryWeight = idf * getBoost(); return queryWeight * queryWeight; } 129 130 public void normalize(float queryNorm) { 131 this.queryNorm = queryNorm; 132 queryWeight *= queryNorm; value = queryWeight * idf; } 135 136 public Scorer scorer(IndexReader reader) throws IOException { 137 if (terms.size() == 0) return null; 139 140 TermPositions[] tps = new TermPositions[terms.size()]; 141 for (int i = 0; i < terms.size(); i++) { 142 TermPositions p = reader.termPositions((Term)terms.elementAt(i)); 143 if (p == null) 144 return null; 145 tps[i] = p; 146 } 147 148 if (slop == 0) return new ExactPhraseScorer(this, tps, getPositions(), similarity, 150 reader.norms(field)); 151 else 152 return 153 new SloppyPhraseScorer(this, tps, getPositions(), similarity, slop, 154 reader.norms(field)); 155 156 } 157 158 public Explanation explain(IndexReader reader, int doc) 159 throws IOException { 160 161 Explanation result = new Explanation(); 162 result.setDescription("weight("+getQuery()+" in "+doc+"), product of:"); 163 164 StringBuffer docFreqs = new StringBuffer (); 165 StringBuffer query = new StringBuffer (); 166 query.append('\"'); 167 for (int i = 0; i < terms.size(); i++) { 168 if (i != 0) { 169 docFreqs.append(" "); 170 query.append(" "); 171 } 172 173 Term term = (Term)terms.elementAt(i); 174 175 docFreqs.append(term.text()); 176 docFreqs.append("="); 177 docFreqs.append(reader.docFreq(term)); 178 179 query.append(term.text()); 180 } 181 query.append('\"'); 182 183 Explanation idfExpl = 184 new Explanation(idf, "idf(" + field + ": " + docFreqs + ")"); 185 186 Explanation queryExpl = new Explanation(); 188 queryExpl.setDescription("queryWeight(" + getQuery() + "), product of:"); 189 190 Explanation boostExpl = new Explanation(getBoost(), "boost"); 191 if (getBoost() != 1.0f) 192 queryExpl.addDetail(boostExpl); 193 queryExpl.addDetail(idfExpl); 194 195 Explanation queryNormExpl = new Explanation(queryNorm,"queryNorm"); 196 queryExpl.addDetail(queryNormExpl); 197 198 queryExpl.setValue(boostExpl.getValue() * 199 idfExpl.getValue() * 200 queryNormExpl.getValue()); 201 202 result.addDetail(queryExpl); 203 204 Explanation fieldExpl = new Explanation(); 206 fieldExpl.setDescription("fieldWeight("+field+":"+query+" in "+doc+ 207 "), product of:"); 208 209 Explanation tfExpl = scorer(reader).explain(doc); 210 fieldExpl.addDetail(tfExpl); 211 fieldExpl.addDetail(idfExpl); 212 213 Explanation fieldNormExpl = new Explanation(); 214 byte[] fieldNorms = reader.norms(field); 215 float fieldNorm = 216 fieldNorms!=null ? Similarity.decodeNorm(fieldNorms[doc]) : 0.0f; 217 fieldNormExpl.setValue(fieldNorm); 218 fieldNormExpl.setDescription("fieldNorm(field="+field+", doc="+doc+")"); 219 fieldExpl.addDetail(fieldNormExpl); 220 221 fieldExpl.setValue(tfExpl.getValue() * 222 idfExpl.getValue() * 223 fieldNormExpl.getValue()); 224 225 result.addDetail(fieldExpl); 226 227 result.setValue(queryExpl.getValue() * fieldExpl.getValue()); 229 230 if (queryExpl.getValue() == 1.0f) 231 return fieldExpl; 232 233 return result; 234 } 235 } 236 237 protected Weight createWeight(Searcher searcher) throws IOException { 238 if (terms.size() == 1) { Term term = (Term)terms.elementAt(0); 240 Query termQuery = new TermQuery(term); 241 termQuery.setBoost(getBoost()); 242 return termQuery.createWeight(searcher); 243 } 244 return new PhraseWeight(searcher); 245 } 246 247 250 public void extractTerms(Set queryTerms) { 251 queryTerms.addAll(terms); 252 } 253 254 255 public String toString(String f) { 256 StringBuffer buffer = new StringBuffer (); 257 if (!field.equals(f)) { 258 buffer.append(field); 259 buffer.append(":"); 260 } 261 262 buffer.append("\""); 263 for (int i = 0; i < terms.size(); i++) { 264 buffer.append(((Term)terms.elementAt(i)).text()); 265 if (i != terms.size()-1) 266 buffer.append(" "); 267 } 268 buffer.append("\""); 269 270 if (slop != 0) { 271 buffer.append("~"); 272 buffer.append(slop); 273 } 274 275 buffer.append(ToStringUtils.boost(getBoost())); 276 277 return buffer.toString(); 278 } 279 280 281 public boolean equals(Object o) { 282 if (!(o instanceof PhraseQuery)) 283 return false; 284 PhraseQuery other = (PhraseQuery)o; 285 return (this.getBoost() == other.getBoost()) 286 && (this.slop == other.slop) 287 && this.terms.equals(other.terms) 288 && this.positions.equals(other.positions); 289 } 290 291 292 public int hashCode() { 293 return Float.floatToIntBits(getBoost()) 294 ^ slop 295 ^ terms.hashCode() 296 ^ positions.hashCode(); 297 } 298 299 } 300 | Popular Tags |