FileDocCategorySizeDatePackage
MultiSearcher.javaAPI DocApache Lucene 2.1.010026Wed Feb 14 10:46:40 GMT 2007org.apache.lucene.search

MultiSearcher

public class MultiSearcher extends Searcher
Implements search over a set of Searchables.

Applications usually need only call the inherited {@link #search(Query)} or {@link #search(Query,Filter)} methods.

Fields Summary
private Searchable[]
searchables
private int[]
starts
private int
maxDoc
Constructors Summary
public MultiSearcher(Searchable[] searchables)
Creates a searcher which searches searchables.


         
       
    this.searchables = searchables;

    starts = new int[searchables.length + 1];	  // build starts array
    for (int i = 0; i < searchables.length; i++) {
      starts[i] = maxDoc;
      maxDoc += searchables[i].maxDoc();          // compute maxDocs
    }
    starts[searchables.length] = maxDoc;
  
Methods Summary
public voidclose()

    for (int i = 0; i < searchables.length; i++)
      searchables[i].close();
  
protected org.apache.lucene.search.WeightcreateWeight(org.apache.lucene.search.Query original)
Create weight in multiple index scenario. Distributed query processing is done in the following steps: 1. rewrite query 2. extract necessary terms 3. collect dfs for these terms from the Searchables 4. create query weight using aggregate dfs. 5. distribute that weight to Searchables 6. merge results Steps 1-4 are done here, 5+6 in the search() methods

return
rewritten queries

    // step 1
    Query rewrittenQuery = rewrite(original);

    // step 2
    Set terms = new HashSet();
    rewrittenQuery.extractTerms(terms);

    // step3
    Term[] allTermsArray = new Term[terms.size()];
    terms.toArray(allTermsArray);
    int[] aggregatedDfs = new int[terms.size()];
    for (int i = 0; i < searchables.length; i++) {
      int[] dfs = searchables[i].docFreqs(allTermsArray);
      for(int j=0; j<aggregatedDfs.length; j++){
        aggregatedDfs[j] += dfs[j];
      }
    }

    HashMap dfMap = new HashMap();
    for(int i=0; i<allTermsArray.length; i++) {
      dfMap.put(allTermsArray[i], new Integer(aggregatedDfs[i]));
    }

    // step4
    int numDocs = maxDoc();
    CachedDfSource cacheSim = new CachedDfSource(dfMap, numDocs);

    return rewrittenQuery.weight(cacheSim);
  
public org.apache.lucene.document.Documentdoc(int n)

    int i = subSearcher(n);			  // find searcher index
    return searchables[i].doc(n - starts[i]);	  // dispatch to searcher
  
public intdocFreq(org.apache.lucene.index.Term term)

    int docFreq = 0;
    for (int i = 0; i < searchables.length; i++)
      docFreq += searchables[i].docFreq(term);
    return docFreq;
  
public org.apache.lucene.search.Explanationexplain(org.apache.lucene.search.Weight weight, int doc)

    int i = subSearcher(doc);			  // find searcher index
    return searchables[i].explain(weight,doc-starts[i]); // dispatch to searcher
  
public org.apache.lucene.search.Searchable[]getSearchables()
Return the array of {@link Searchable}s this searches.

    return searchables;
  
protected int[]getStarts()

  	return starts;
  
public intmaxDoc()

    return maxDoc;
  
public org.apache.lucene.search.Queryrewrite(org.apache.lucene.search.Query original)

    Query[] queries = new Query[searchables.length];
    for (int i = 0; i < searchables.length; i++) {
      queries[i] = searchables[i].rewrite(original);
    }
    return queries[0].combine(queries);
  
public org.apache.lucene.search.TopDocssearch(org.apache.lucene.search.Weight weight, org.apache.lucene.search.Filter filter, int nDocs)


    HitQueue hq = new HitQueue(nDocs);
    int totalHits = 0;

    for (int i = 0; i < searchables.length; i++) { // search each searcher
      TopDocs docs = searchables[i].search(weight, filter, nDocs);
      totalHits += docs.totalHits;		  // update totalHits
      ScoreDoc[] scoreDocs = docs.scoreDocs;
      for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
	ScoreDoc scoreDoc = scoreDocs[j];
        scoreDoc.doc += starts[i];                // convert doc
        if(!hq.insert(scoreDoc))
            break;                                // no more scores > minScore
      }
    }

    ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
    for (int i = hq.size()-1; i >= 0; i--)	  // put docs in array
      scoreDocs[i] = (ScoreDoc)hq.pop();
    
    float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score;
    
    return new TopDocs(totalHits, scoreDocs, maxScore);
  
public org.apache.lucene.search.TopFieldDocssearch(org.apache.lucene.search.Weight weight, org.apache.lucene.search.Filter filter, int n, org.apache.lucene.search.Sort sort)

    FieldDocSortedHitQueue hq = null;
    int totalHits = 0;

    float maxScore=Float.NEGATIVE_INFINITY;
    
    for (int i = 0; i < searchables.length; i++) { // search each searcher
      TopFieldDocs docs = searchables[i].search (weight, filter, n, sort);
      
      if (hq == null) hq = new FieldDocSortedHitQueue (docs.fields, n);
      totalHits += docs.totalHits;		  // update totalHits
      maxScore = Math.max(maxScore, docs.getMaxScore());
      ScoreDoc[] scoreDocs = docs.scoreDocs;
      for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
        ScoreDoc scoreDoc = scoreDocs[j];
        scoreDoc.doc += starts[i];                // convert doc
        if (!hq.insert (scoreDoc))
          break;                                  // no more scores > minScore
      }
    }

    ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
    for (int i = hq.size() - 1; i >= 0; i--)	  // put docs in array
      scoreDocs[i] = (ScoreDoc) hq.pop();

    return new TopFieldDocs (totalHits, scoreDocs, hq.getFields(), maxScore);
  
public voidsearch(org.apache.lucene.search.Weight weight, org.apache.lucene.search.Filter filter, org.apache.lucene.search.HitCollector results)

    for (int i = 0; i < searchables.length; i++) {

      final int start = starts[i];

      searchables[i].search(weight, filter, new HitCollector() {
	  public void collect(int doc, float score) {
	    results.collect(doc + start, score);
	  }
	});

    }
  
public intsubDoc(int n)
Returns the document number of document n within its sub-index.

    return n - starts[subSearcher(n)];
  
public intsubSearcher(int n)
Returns index of the searcher for document n in the array used to construct this searcher.

                 // find searcher for doc n:
    // replace w/ call to Arrays.binarySearch in Java 1.2
    int lo = 0;					  // search starts array
    int hi = searchables.length - 1;		  // for first element less
						  // than n, return its index
    while (hi >= lo) {
      int mid = (lo + hi) >> 1;
      int midValue = starts[mid];
      if (n < midValue)
	hi = mid - 1;
      else if (n > midValue)
	lo = mid + 1;
      else {                                      // found a match
        while (mid+1 < searchables.length && starts[mid+1] == midValue) {
          mid++;                                  // scan to last match
        }
	return mid;
      }
    }
    return hi;