1 package org.apache.lucene.search; 2 3 18 19 import java.io.IOException ; 20 import java.util.HashMap ; 21 import java.util.HashSet ; 22 import java.util.Map ; 23 import java.util.Set ; 24 25 import org.apache.lucene.document.Document; 26 import org.apache.lucene.index.Term; 27 28 33 public class MultiSearcher extends Searcher { 34 39 private static class CachedDfSource extends Searcher { 40 private Map dfMap; private int maxDoc; 43 public CachedDfSource(Map dfMap, int maxDoc) { 44 this.dfMap = dfMap; 45 this.maxDoc = maxDoc; 46 } 47 48 public int docFreq(Term term) { 49 int df; 50 try { 51 df = ((Integer ) dfMap.get(term)).intValue(); 52 } catch (NullPointerException e) { 53 throw new IllegalArgumentException ("df for term " + term.text() 54 + " not available"); 55 } 56 return df; 57 } 58 59 public int[] docFreqs(Term[] terms) { 60 int[] result = new int[terms.length]; 61 for (int i = 0; i < terms.length; i++) { 62 result[i] = docFreq(terms[i]); 63 } 64 return result; 65 } 66 67 public int maxDoc() { 68 return maxDoc; 69 } 70 71 public Query rewrite(Query query) { 72 return query; 77 } 78 79 public void close() { 80 throw new UnsupportedOperationException (); 81 } 82 83 public Document doc(int i) { 84 throw new UnsupportedOperationException (); 85 } 86 87 public Explanation explain(Weight weight,int doc) { 88 throw new UnsupportedOperationException (); 89 } 90 91 public void search(Weight weight, Filter filter, HitCollector results) { 92 throw new UnsupportedOperationException (); 93 } 94 95 public TopDocs search(Weight weight,Filter filter,int n) { 96 throw new UnsupportedOperationException (); 97 } 98 99 public TopFieldDocs search(Weight weight,Filter filter,int n,Sort sort) { 100 throw new UnsupportedOperationException (); 101 } 102 }; 103 104 105 private Searchable[] searchables; 106 private int[] starts; 107 private int maxDoc = 0; 108 109 110 public MultiSearcher(Searchable[] searchables) throws IOException { 111 this.searchables = searchables; 112 113 starts = new int[searchables.length + 1]; for (int i = 0; i < searchables.length; i++) { 115 starts[i] = maxDoc; 116 maxDoc += searchables[i].maxDoc(); } 118 starts[searchables.length] = maxDoc; 119 } 120 121 122 public Searchable[] getSearchables() { 123 return searchables; 124 } 125 126 protected int[] getStarts() { 127 return starts; 128 } 129 130 public void close() throws IOException { 132 for (int i = 0; i < searchables.length; i++) 133 searchables[i].close(); 134 } 135 136 public int docFreq(Term term) throws IOException { 137 int docFreq = 0; 138 for (int i = 0; i < searchables.length; i++) 139 docFreq += searchables[i].docFreq(term); 140 return docFreq; 141 } 142 143 public Document doc(int n) throws IOException { 145 int i = subSearcher(n); return searchables[i].doc(n - starts[i]); } 148 149 152 public int searcherIndex(int n) { 153 return subSearcher(n); 154 } 155 156 158 public int subSearcher(int n) { int lo = 0; int hi = searchables.length - 1; while (hi >= lo) { 164 int mid = (lo + hi) >> 1; 165 int midValue = starts[mid]; 166 if (n < midValue) 167 hi = mid - 1; 168 else if (n > midValue) 169 lo = mid + 1; 170 else { while (mid+1 < searchables.length && starts[mid+1] == midValue) { 172 mid++; } 174 return mid; 175 } 176 } 177 return hi; 178 } 179 180 182 public int subDoc(int n) { 183 return n - starts[subSearcher(n)]; 184 } 185 186 public int maxDoc() throws IOException { 187 return maxDoc; 188 } 189 190 public TopDocs search(Weight weight, Filter filter, int nDocs) 191 throws IOException { 192 193 HitQueue hq = new HitQueue(nDocs); 194 int totalHits = 0; 195 196 for (int i = 0; i < searchables.length; i++) { TopDocs docs = searchables[i].search(weight, filter, nDocs); 198 totalHits += docs.totalHits; ScoreDoc[] scoreDocs = docs.scoreDocs; 200 for (int j = 0; j < scoreDocs.length; j++) { ScoreDoc scoreDoc = scoreDocs[j]; 202 scoreDoc.doc += starts[i]; if(!hq.insert(scoreDoc)) 204 break; } 206 } 207 208 ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()]; 209 for (int i = hq.size()-1; i >= 0; i--) scoreDocs[i] = (ScoreDoc)hq.pop(); 211 212 float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score; 213 214 return new TopDocs(totalHits, scoreDocs, maxScore); 215 } 216 217 public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort) 218 throws IOException { 219 FieldDocSortedHitQueue hq = null; 220 int totalHits = 0; 221 222 float maxScore=Float.NEGATIVE_INFINITY; 223 224 for (int i = 0; i < searchables.length; i++) { TopFieldDocs docs = searchables[i].search (weight, filter, n, sort); 226 227 if (hq == null) hq = new FieldDocSortedHitQueue (docs.fields, n); 228 totalHits += docs.totalHits; maxScore = Math.max(maxScore, docs.getMaxScore()); 230 ScoreDoc[] scoreDocs = docs.scoreDocs; 231 for (int j = 0; j < scoreDocs.length; j++) { ScoreDoc scoreDoc = scoreDocs[j]; 233 scoreDoc.doc += starts[i]; if (!hq.insert (scoreDoc)) 235 break; } 237 } 238 239 ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()]; 240 for (int i = hq.size() - 1; i >= 0; i--) scoreDocs[i] = (ScoreDoc) hq.pop(); 242 243 return new TopFieldDocs (totalHits, scoreDocs, hq.getFields(), maxScore); 244 } 245 246 247 public void search(Weight weight, Filter filter, final HitCollector results) 249 throws IOException { 250 for (int i = 0; i < searchables.length; i++) { 251 252 final int start = starts[i]; 253 254 searchables[i].search(weight, filter, new HitCollector() { 255 public void collect(int doc, float score) { 256 results.collect(doc + start, score); 257 } 258 }); 259 260 } 261 } 262 263 public Query rewrite(Query original) throws IOException { 264 Query[] queries = new Query[searchables.length]; 265 for (int i = 0; i < searchables.length; i++) { 266 queries[i] = searchables[i].rewrite(original); 267 } 268 return queries[0].combine(queries); 269 } 270 271 public Explanation explain(Weight weight, int doc) throws IOException { 272 int i = subSearcher(doc); return searchables[i].explain(weight,doc-starts[i]); } 275 276 291 protected Weight createWeight(Query original) throws IOException { 292 Query rewrittenQuery = rewrite(original); 294 295 Set terms = new HashSet (); 297 rewrittenQuery.extractTerms(terms); 298 299 Term[] allTermsArray = new Term[terms.size()]; 301 terms.toArray(allTermsArray); 302 int[] aggregatedDfs = new int[terms.size()]; 303 for (int i = 0; i < searchables.length; i++) { 304 int[] dfs = searchables[i].docFreqs(allTermsArray); 305 for(int j=0; j<aggregatedDfs.length; j++){ 306 aggregatedDfs[j] += dfs[j]; 307 } 308 } 309 310 HashMap dfMap = new HashMap (); 311 for(int i=0; i<allTermsArray.length; i++) { 312 dfMap.put(allTermsArray[i], new Integer (aggregatedDfs[i])); 313 } 314 315 int numDocs = maxDoc(); 317 CachedDfSource cacheSim = new CachedDfSource(dfMap, numDocs); 318 319 return rewrittenQuery.weight(cacheSim); 320 } 321 322 } 323 | Popular Tags |