| Method from org.apache.lucene.search.MultiSearcher Detail: |
public void close() throws IOException {
for (int i = 0; i < searchables.length; i++)
searchables[i].close();
}
|
protected Weight createWeight(Query original) throws IOException {
// 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, getSimilarity());
return rewrittenQuery.weight(cacheSim);
}
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 |
public Document doc(int n) throws IOException, CorruptIndexException {
int i = subSearcher(n); // find searcher index
return searchables[i].doc(n - starts[i]); // dispatch to searcher
}
|
public Document doc(int n,
FieldSelector fieldSelector) throws IOException, CorruptIndexException {
int i = subSearcher(n); // find searcher index
return searchables[i].doc(n - starts[i], fieldSelector); // dispatch to searcher
}
|
public int docFreq(Term term) throws IOException {
int docFreq = 0;
for (int i = 0; i < searchables.length; i++)
docFreq += searchables[i].docFreq(term);
return docFreq;
}
|
public Explanation explain(Weight weight,
int doc) throws IOException {
int i = subSearcher(doc); // find searcher index
return searchables[i].explain(weight,doc-starts[i]); // dispatch to searcher
}
|
public Searchable[] getSearchables() {
return searchables;
}
|
protected int[] getStarts() {
return starts;
}
|
public int maxDoc() throws IOException {
return maxDoc;
}
|
public Query rewrite(Query original) throws IOException {
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 TopDocs search(Weight weight,
Filter filter,
int nDocs) throws IOException {
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 void search(Weight weight,
Filter filter,
HitCollector results) throws IOException {
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 TopFieldDocs search(Weight weight,
Filter filter,
int n,
Sort sort) throws IOException {
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 int subDoc(int n) {
return n - starts[subSearcher(n)];
}
Returns the document number of document n within its
sub-index. |
public int subSearcher(int n) {
// 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;
}
Returns index of the searcher for document n in the array
used to construct this searcher. |