1 package org.apache.lucene.search; 2 3 18 19 import org.apache.lucene.index.IndexReader; 20 21 import java.io.IOException ; 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 import java.util.Collection ; 25 26 41 public class DisjunctionMaxQuery extends Query { 42 43 44 private ArrayList disjuncts = new ArrayList (); 45 46 47 private float tieBreakerMultiplier = 0.0f; 48 49 55 public DisjunctionMaxQuery(float tieBreakerMultiplier) { 56 this.tieBreakerMultiplier = tieBreakerMultiplier; 57 } 58 59 64 public DisjunctionMaxQuery(Collection disjuncts, float tieBreakerMultiplier) { 65 this.tieBreakerMultiplier = tieBreakerMultiplier; 66 add(disjuncts); 67 } 68 69 72 public void add(Query query) { 73 disjuncts.add(query); 74 } 75 76 79 public void add(Collection disjuncts) { 80 this.disjuncts.addAll(disjuncts); 81 } 82 83 84 public Iterator iterator() { 85 return disjuncts.iterator(); 86 } 87 88 89 private class DisjunctionMaxWeight implements Weight { 90 91 private Searcher searcher; private ArrayList weights = new ArrayList (); 94 95 public DisjunctionMaxWeight(Searcher searcher) throws IOException { 96 this.searcher = searcher; 97 for (int i = 0; i < disjuncts.size(); i++) 98 weights.add(((Query) disjuncts.get(i)).createWeight(searcher)); 99 } 100 101 102 public Query getQuery() { return DisjunctionMaxQuery.this; } 103 104 105 public float getValue() { return getBoost(); } 106 107 108 public float sumOfSquaredWeights() throws IOException { 109 float max = 0.0f, sum = 0.0f; 110 for (int i = 0; i < weights.size(); i++) { 111 float sub = ((Weight) weights.get(i)).sumOfSquaredWeights(); 112 sum += sub; 113 max = Math.max(max, sub); 114 } 115 return (((sum - max) * tieBreakerMultiplier * tieBreakerMultiplier) + max) * getBoost() * getBoost(); 116 } 117 118 119 public void normalize(float norm) { 120 norm *= getBoost(); for (int i = 0 ; i < weights.size(); i++) 122 ((Weight) weights.get(i)).normalize(norm); 123 } 124 125 126 public Scorer scorer(IndexReader reader) throws IOException { 127 DisjunctionMaxScorer result = new DisjunctionMaxScorer(tieBreakerMultiplier, getSimilarity(searcher)); 128 for (int i = 0 ; i < weights.size(); i++) { 129 Weight w = (Weight) weights.get(i); 130 Scorer subScorer = w.scorer(reader); 131 if (subScorer == null) return null; 132 result.add(subScorer); 133 } 134 return result; 135 } 136 137 138 public Explanation explain(IndexReader reader, int doc) throws IOException { 139 if ( disjuncts.size() == 1) return ((Weight) weights.get(0)).explain(reader,doc); 140 Explanation result = new Explanation(); 141 float max = 0.0f, sum = 0.0f; 142 result.setDescription(tieBreakerMultiplier == 0.0f ? "max of:" : "max plus " + tieBreakerMultiplier + " times others of:"); 143 for (int i = 0 ; i < weights.size(); i++) { 144 Explanation e = ((Weight) weights.get(i)).explain(reader, doc); 145 if (e.getValue() > 0) { 146 result.addDetail(e); 147 sum += e.getValue(); 148 max = Math.max(max, e.getValue()); 149 } 150 } 151 result.setValue(max + (sum - max)*tieBreakerMultiplier); 152 return result; 153 } 154 155 } 157 158 protected Weight createWeight(Searcher searcher) throws IOException { 159 return new DisjunctionMaxWeight(searcher); 160 } 161 162 165 public Query rewrite(IndexReader reader) throws IOException { 166 if (disjuncts.size() == 1) { 167 Query singleton = (Query) disjuncts.get(0); 168 Query result = singleton.rewrite(reader); 169 if (getBoost() != 1.0f) { 170 if (result == singleton) result = (Query)result.clone(); 171 result.setBoost(getBoost() * result.getBoost()); 172 } 173 return result; 174 } 175 DisjunctionMaxQuery clone = null; 176 for (int i = 0 ; i < disjuncts.size(); i++) { 177 Query clause = (Query) disjuncts.get(i); 178 Query rewrite = clause.rewrite(reader); 179 if (rewrite != clause) { 180 if (clone == null) clone = (DisjunctionMaxQuery)this.clone(); 181 clone.disjuncts.set(i, rewrite); 182 } 183 } 184 if (clone != null) return clone; 185 else return this; 186 } 187 188 190 public Object clone() { 191 DisjunctionMaxQuery clone = (DisjunctionMaxQuery)super.clone(); 192 clone.disjuncts = (ArrayList )this.disjuncts.clone(); 193 return clone; 194 } 195 196 200 public String toString(String field) { 201 StringBuffer buffer = new StringBuffer (); 202 buffer.append("("); 203 for (int i = 0 ; i < disjuncts.size(); i++) { 204 Query subquery = (Query) disjuncts.get(i); 205 if (subquery instanceof BooleanQuery) { buffer.append("("); 207 buffer.append(subquery.toString(field)); 208 buffer.append(")"); 209 } 210 else buffer.append(subquery.toString(field)); 211 if (i != disjuncts.size()-1) buffer.append(" | "); 212 } 213 buffer.append(")"); 214 if (tieBreakerMultiplier != 0.0f) { 215 buffer.append("~"); 216 buffer.append(tieBreakerMultiplier); 217 } 218 if (getBoost() != 1.0) { 219 buffer.append("^"); 220 buffer.append(getBoost()); 221 } 222 return buffer.toString(); 223 } 224 225 229 public boolean equals(Object o) { 230 if (! (o instanceof DisjunctionMaxQuery) ) return false; 231 DisjunctionMaxQuery other = (DisjunctionMaxQuery)o; 232 return this.getBoost() == other.getBoost() 233 && this.tieBreakerMultiplier == other.tieBreakerMultiplier 234 && this.disjuncts.equals(other.disjuncts); 235 } 236 237 240 public int hashCode() { 241 return Float.floatToIntBits(getBoost()) 242 + Float.floatToIntBits(tieBreakerMultiplier) 243 + disjuncts.hashCode(); 244 } 245 246 } 247 | Popular Tags |