1 package org.apache.lucene.search; 2 3 18 19 import org.apache.lucene.index.IndexReader; 20 import org.apache.lucene.index.Term; 21 import org.apache.lucene.util.PriorityQueue; 22 import org.apache.lucene.util.ToStringUtils; 23 24 import java.io.IOException ; 25 26 29 public final class FuzzyQuery extends MultiTermQuery { 30 31 public final static float defaultMinSimilarity = 0.5f; 32 public final static int defaultPrefixLength = 0; 33 34 private float minimumSimilarity; 35 private int prefixLength; 36 37 53 public FuzzyQuery(Term term, float minimumSimilarity, int prefixLength) throws IllegalArgumentException { 54 super(term); 55 56 if (minimumSimilarity >= 1.0f) 57 throw new IllegalArgumentException ("minimumSimilarity >= 1"); 58 else if (minimumSimilarity < 0.0f) 59 throw new IllegalArgumentException ("minimumSimilarity < 0"); 60 if (prefixLength < 0) 61 throw new IllegalArgumentException ("prefixLength < 0"); 62 63 this.minimumSimilarity = minimumSimilarity; 64 this.prefixLength = prefixLength; 65 } 66 67 70 public FuzzyQuery(Term term, float minimumSimilarity) throws IllegalArgumentException { 71 this(term, minimumSimilarity, defaultPrefixLength); 72 } 73 74 77 public FuzzyQuery(Term term) { 78 this(term, defaultMinSimilarity, defaultPrefixLength); 79 } 80 81 85 public float getMinSimilarity() { 86 return minimumSimilarity; 87 } 88 89 94 public int getPrefixLength() { 95 return prefixLength; 96 } 97 98 protected FilteredTermEnum getEnum(IndexReader reader) throws IOException { 99 return new FuzzyTermEnum(reader, getTerm(), minimumSimilarity, prefixLength); 100 } 101 102 public Query rewrite(IndexReader reader) throws IOException { 103 FilteredTermEnum enumerator = getEnum(reader); 104 int maxClauseCount = BooleanQuery.getMaxClauseCount(); 105 ScoreTermQueue stQueue = new ScoreTermQueue(maxClauseCount); 106 107 try { 108 do { 109 float minScore = 0.0f; 110 float score = 0.0f; 111 Term t = enumerator.term(); 112 if (t != null) { 113 score = enumerator.difference(); 114 if(stQueue.size() < maxClauseCount || score > minScore){ 117 stQueue.insert(new ScoreTerm(t, score)); 118 minScore = ((ScoreTerm)stQueue.top()).score; } 120 } 121 } while (enumerator.next()); 122 } finally { 123 enumerator.close(); 124 } 125 126 BooleanQuery query = new BooleanQuery(true); 127 int size = stQueue.size(); 128 for(int i = 0; i < size; i++){ 129 ScoreTerm st = (ScoreTerm) stQueue.pop(); 130 TermQuery tq = new TermQuery(st.term); tq.setBoost(getBoost() * st.score); query.add(tq, BooleanClause.Occur.SHOULD); } 134 135 return query; 136 } 137 138 public String toString(String field) { 139 StringBuffer buffer = new StringBuffer (); 140 Term term = getTerm(); 141 if (!term.field().equals(field)) { 142 buffer.append(term.field()); 143 buffer.append(":"); 144 } 145 buffer.append(term.text()); 146 buffer.append('~'); 147 buffer.append(Float.toString(minimumSimilarity)); 148 buffer.append(ToStringUtils.boost(getBoost())); 149 return buffer.toString(); 150 } 151 152 private static class ScoreTerm{ 153 public Term term; 154 public float score; 155 156 public ScoreTerm(Term term, float score){ 157 this.term = term; 158 this.score = score; 159 } 160 } 161 162 private static class ScoreTermQueue extends PriorityQueue { 163 164 public ScoreTermQueue(int size){ 165 initialize(size); 166 } 167 168 171 protected boolean lessThan(Object a, Object b) { 172 ScoreTerm termA = (ScoreTerm)a; 173 ScoreTerm termB = (ScoreTerm)b; 174 if (termA.score == termB.score) 175 return termA.term.compareTo(termB.term) > 0; 176 else 177 return termA.score < termB.score; 178 } 179 180 } 181 182 public boolean equals(Object o) { 183 if (this == o) return true; 184 if (!(o instanceof FuzzyQuery)) return false; 185 if (!super.equals(o)) return false; 186 187 final FuzzyQuery fuzzyQuery = (FuzzyQuery) o; 188 189 if (minimumSimilarity != fuzzyQuery.minimumSimilarity) return false; 190 if (prefixLength != fuzzyQuery.prefixLength) return false; 191 192 return true; 193 } 194 195 public int hashCode() { 196 int result = super.hashCode(); 197 result = 29 * result + minimumSimilarity != +0.0f ? Float.floatToIntBits(minimumSimilarity) : 0; 198 result = 29 * result + prefixLength; 199 return result; 200 } 201 } 202 | Popular Tags |