19 using System.Collections.Generic;
21 using Lucene.Net.Support;
22 using Lucene.Net.Util;
23 using Document = Lucene.Net.Documents.Document;
27 using Term = Lucene.Net.Index.Term;
30 namespace Lucene.Net.Search
40 private class AnonymousClassCollector:
Collector
42 public AnonymousClassCollector(Lucene.Net.Search.Collector collector,
int start,
MultiSearcher enclosingInstance)
44 InitBlock(collector, start, enclosingInstance);
46 private void InitBlock(Lucene.Net.Search.Collector collector,
int start,
MultiSearcher enclosingInstance)
48 this.collector = collector;
50 this.enclosingInstance = enclosingInstance;
52 private Lucene.Net.
Search.Collector collector;
59 return enclosingInstance;
63 public override void SetScorer(
Scorer scorer)
65 collector.SetScorer(scorer);
67 public override void Collect(
int doc)
69 collector.Collect(doc);
71 public override void SetNextReader(
IndexReader reader,
int docBase)
73 collector.SetNextReader(reader, start + docBase);
76 public override bool AcceptsDocsOutOfOrder
78 get {
return collector.AcceptsDocsOutOfOrder; }
86 private class CachedDfSource:
Searcher
88 private readonly Dictionary<Term,int> dfMap;
89 private readonly
int maxDoc;
91 public CachedDfSource(Dictionary<Term,int> dfMap,
int maxDoc,
Similarity similarity)
98 public override int DocFreq(
Term term)
105 catch (KeyNotFoundException)
107 throw new System.ArgumentException(
"df for term " + term.Text +
" not available");
112 public override int[] DocFreqs(
Term[] terms)
114 int[] result =
new int[terms.Length];
115 for (
int i = 0; i < terms.Length; i++)
117 result[i] = DocFreq(terms[i]);
122 public override int MaxDoc
124 get {
return maxDoc; }
137 protected override void Dispose(
bool disposing)
139 throw new System.NotSupportedException();
144 throw new System.NotSupportedException();
149 throw new System.NotSupportedException();
154 throw new System.NotSupportedException();
159 throw new System.NotSupportedException();
164 throw new System.NotSupportedException();
169 throw new System.NotSupportedException();
174 private int[] starts;
175 private int maxDoc = 0;
177 private bool isDisposed;
182 this.searchables = searchables;
184 starts =
new int[searchables.Length + 1];
185 for (
int i = 0; i < searchables.Length; i++)
188 maxDoc += searchables[i].
MaxDoc;
190 starts[searchables.Length] = maxDoc;
199 protected internal virtual int[] GetStarts()
204 protected override void Dispose(
bool disposing)
206 if (isDisposed)
return;
210 for (
int i = 0; i < searchables.Length; i++)
211 searchables[i].Close();
217 public override int DocFreq(
Term term)
220 for (
int i = 0; i < searchables.Length; i++)
221 docFreq += searchables[i].DocFreq(term);
228 int i = SubSearcher(n);
229 return searchables[i].Doc(n - starts[i]);
235 int i = SubSearcher(n);
236 return searchables[i].Doc(n - starts[i], fieldSelector);
242 public virtual int SubSearcher(
int n)
251 public virtual int SubDoc(
int n)
253 return n - starts[SubSearcher(n)];
256 public override int MaxDoc
258 get {
return maxDoc; }
266 var lockObj =
new object();
267 for (
int i = 0; i < searchables.Length; i++)
271 TopDocs docs = MultiSearcherCallableNoSort(
ThreadLock.
NullLock, lockObj, searchables[i], weight, filter, nDocs, hq, i, starts);
276 for (
int i = hq.Size() - 1; i >= 0; i--)
278 scoreDocs2[i] = hq.Pop();
280 float maxScore = (totalHits == 0)?System.Single.NegativeInfinity:scoreDocs2[0].
Score;
282 return new TopDocs(totalHits, scoreDocs2, maxScore);
290 float maxScore = System.Single.NegativeInfinity;
292 var lockObj =
new object();
293 for (
int i = 0; i < searchables.Length; i++)
300 maxScore = System.Math.Max(maxScore, docs.
MaxScore);
304 for (
int i = hq.Size() - 1; i >= 0; i--)
306 scoreDocs2[i] = hq.Pop();
308 return new TopFieldDocs(totalHits, scoreDocs2, hq.GetFields(), maxScore);
314 for (
int i = 0; i < searchables.Length; i++)
316 int start = starts[i];
318 Collector hc =
new AnonymousClassCollector(collector, start,
this);
319 searchables[i].Search(weight, filter, hc);
325 Query[] queries =
new Query[searchables.Length];
326 for (
int i = 0; i < searchables.Length; i++)
328 queries[i] = searchables[i].
Rewrite(original);
330 return queries[0].
Combine(queries);
335 int i = SubSearcher(doc);
336 return searchables[i].Explain(weight, doc - starts[i]);
357 Query rewrittenQuery = Rewrite(original);
360 ISet<Term> terms = Lucene.Net.Support.Compatibility.SetFactory.CreateHashSet<
Term>();
364 Term[] allTermsArray = terms.ToArray();
365 int[] aggregatedDfs =
new int[terms.Count];
366 for (
int i = 0; i < searchables.Length; i++)
368 int[] dfs = searchables[i].DocFreqs(allTermsArray);
369 for (
int j = 0; j < aggregatedDfs.Length; j++)
371 aggregatedDfs[j] += dfs[j];
375 var dfMap =
new Dictionary<Term, int>();
376 for (
int i = 0; i < allTermsArray.Length; i++)
378 dfMap[allTermsArray[i]] = aggregatedDfs[i];
382 int numDocs = MaxDoc;
383 CachedDfSource cacheSim =
new CachedDfSource(dfMap, numDocs,
Similarity);
385 return rewrittenQuery.
Weight(cacheSim);
388 internal Func<ThreadLock, object, Searchable, Weight, Filter, int, HitQueue, int, int[], TopDocs> MultiSearcherCallableNoSort =
389 (threadLock, lockObj, searchable, weight, filter, nDocs, hq, i, starts) =>
391 TopDocs docs = searchable.Search(weight, filter, nDocs);
393 for(
int j = 0; j < scoreDocs.Length; j++)
396 scoreDoc.
Doc += starts[i];
400 threadLock.Enter(lockObj);
401 if (scoreDoc == hq.InsertWithOverflow(scoreDoc))
406 threadLock.Exit(lockObj);
412 internal Func<ThreadLock, object, Searchable, Weight, Filter, int, FieldDocSortedHitQueue, Sort, int, int[], TopFieldDocs>
413 MultiSearcherCallableWithSort = (threadLock, lockObj, searchable, weight, filter, nDocs, hq, sort, i, starts) =>
415 TopFieldDocs docs = searchable.Search(weight, filter, nDocs, sort);
419 for (
int j = 0; j < docs.fields.Length; j++)
421 if (docs.fields[j].Type ==
SortField.DOC)
424 for (
int j2 = 0; j2 < docs.ScoreDocs.Length; j2++)
426 FieldDoc fd = (FieldDoc) docs.
ScoreDocs[j2];
427 fd.fields[j] = (
int)fd.fields[j] + starts[i];
434 threadLock.Enter(lockObj);
435 hq.SetFields(docs.fields);
439 threadLock.Exit(lockObj);
442 ScoreDoc[] scoreDocs = docs.ScoreDocs;
443 for (
int j = 0; j < scoreDocs.Length; j++)
445 FieldDoc fieldDoc = (FieldDoc) scoreDocs[j];
446 fieldDoc.
Doc += starts[i];
450 if (fieldDoc == hq.InsertWithOverflow(fieldDoc))