public override Explanation Explain(IndexSearcher searcher, Explanation firstPassExplanation, int docID) { TopDocs oneHit = new TopDocs(1, new ScoreDoc[] { new ScoreDoc(docID, firstPassExplanation.Value) }); TopDocs hits = Rescore(searcher, oneHit, 1); Debug.Assert(hits.TotalHits == 1); // TODO: if we could ask the Sort to explain itself then // we wouldn't need the separate ExpressionRescorer... Explanation result = new Explanation(0.0f, "sort field values for sort=" + sort.ToString()); // Add first pass: Explanation first = new Explanation(firstPassExplanation.Value, "first pass score"); first.AddDetail(firstPassExplanation); result.AddDetail(first); FieldDoc fieldDoc = (FieldDoc)hits.ScoreDocs[0]; // Add sort values: SortField[] sortFields = sort.GetSort(); for (int i = 0; i < sortFields.Length; i++) { result.AddDetail(new Explanation(0.0f, "sort field " + sortFields[i].ToString() + " value=" + fieldDoc.Fields[i])); } return(result); }
public SearcherCallableWithSort(ReentrantLock @lock, IndexSearcher searcher, LeafSlice slice, Weight weight, FieldDoc after, int nDocs, TopFieldCollector hq, Sort sort, bool doDocScores, bool doMaxScore) { this.@lock = @lock; this.searcher = searcher; this.weight = weight; this.nDocs = nDocs; this.hq = hq; this.sort = sort; this.slice = slice; this.after = after; this.doDocScores = doDocScores; this.doMaxScore = doMaxScore; }
/// <summary> /// Just like <see cref="Search(Weight, int, Sort, bool, bool)"/>, but you choose /// whether or not the fields in the returned <see cref="FieldDoc"/> instances should /// be set by specifying <paramref name="fillFields"/>. /// </summary> protected virtual TopFieldDocs Search(Weight weight, FieldDoc after, int nDocs, Sort sort, bool fillFields, bool doDocScores, bool doMaxScore) { if (sort == null) { throw new System.ArgumentNullException("Sort must not be null"); } int limit = reader.MaxDoc; if (limit == 0) { limit = 1; } nDocs = Math.Min(nDocs, limit); if (executor == null) { // use all leaves here! return(Search(m_leafContexts, weight, after, nDocs, sort, fillFields, doDocScores, doMaxScore)); } else { TopFieldCollector topCollector = TopFieldCollector.Create(sort, nDocs, after, fillFields, doDocScores, doMaxScore, false); ReentrantLock @lock = new ReentrantLock(); ExecutionHelper <TopFieldDocs> runner = new ExecutionHelper <TopFieldDocs>(executor); for (int i = 0; i < m_leafSlices.Length; i++) // search each leaf slice { runner.Submit(new SearcherCallableWithSort(@lock, this, m_leafSlices[i], weight, after, nDocs, topCollector, sort, doDocScores, doMaxScore)); } int totalHits = 0; float maxScore = float.NegativeInfinity; foreach (TopFieldDocs topFieldDocs in runner) { if (topFieldDocs.TotalHits != 0) { totalHits += topFieldDocs.TotalHits; maxScore = Math.Max(maxScore, topFieldDocs.MaxScore); } } TopFieldDocs topDocs = (TopFieldDocs)topCollector.GetTopDocs(); return(new TopFieldDocs(totalHits, topDocs.ScoreDocs, topDocs.Fields, topDocs.MaxScore)); } }
// Returns true if first is < second protected internal override bool LessThan(ShardRef first, ShardRef second) { Debug.Assert(first != second); FieldDoc firstFD = (FieldDoc)shardHits[first.ShardIndex][first.HitIndex]; FieldDoc secondFD = (FieldDoc)shardHits[second.ShardIndex][second.HitIndex]; //System.out.println(" lessThan:\n first=" + first + " doc=" + firstFD.doc + " score=" + firstFD.score + "\n second=" + second + " doc=" + secondFD.doc + " score=" + secondFD.score); for (int compIDX = 0; compIDX < comparers.Length; compIDX++) { FieldComparer comp = comparers[compIDX]; //System.out.println(" cmp idx=" + compIDX + " cmp1=" + firstFD.fields[compIDX] + " cmp2=" + secondFD.fields[compIDX] + " reverse=" + reverseMul[compIDX]); int cmp = reverseMul[compIDX] * comp.CompareValues(firstFD.Fields[compIDX], secondFD.Fields[compIDX]); if (cmp != 0) { //System.out.println(" return " + (cmp < 0)); return(cmp < 0); } } // Tie break: earlier shard wins if (first.ShardIndex < second.ShardIndex) { //System.out.println(" return tb true"); return(true); } else if (first.ShardIndex > second.ShardIndex) { //System.out.println(" return tb false"); return(false); } else { // Tie break in same shard: resolve however the // shard had resolved it: //System.out.println(" return tb " + (first.hitIndex < second.hitIndex)); Debug.Assert(first.HitIndex != second.HitIndex); return(first.HitIndex < second.HitIndex); } }
public MergeSortQueue(Sort sort, TopDocs[] shardHits) : base(shardHits.Length) { this.shardHits = new ScoreDoc[shardHits.Length][]; for (int shardIDX = 0; shardIDX < shardHits.Length; shardIDX++) { ScoreDoc[] shard = shardHits[shardIDX].ScoreDocs; //System.out.println(" init shardIdx=" + shardIDX + " hits=" + shard); if (shard != null) { this.shardHits[shardIDX] = shard; // Fail gracefully if API is misused: for (int hitIDX = 0; hitIDX < shard.Length; hitIDX++) { ScoreDoc sd = shard[hitIDX]; if (!(sd is FieldDoc)) { throw new System.ArgumentException("shard " + shardIDX + " was not sorted by the provided Sort (expected FieldDoc but got ScoreDoc)"); } FieldDoc fd = (FieldDoc)sd; if (fd.Fields == null) { throw new System.ArgumentException("shard " + shardIDX + " did not set sort field values (FieldDoc.fields is null); you must pass fillFields=true to IndexSearcher.search on each shard"); } } } } SortField[] sortFields = sort.GetSort(); comparers = new FieldComparer[sortFields.Length]; reverseMul = new int[sortFields.Length]; for (int compIDX = 0; compIDX < sortFields.Length; compIDX++) { SortField sortField = sortFields[compIDX]; comparers[compIDX] = sortField.GetComparer(1, compIDX); reverseMul[compIDX] = sortField.IsReverse ? -1 : 1; } }
/// <summary> /// Just like <see cref="Search(Weight, int, Sort, bool, bool)"/>, but you choose /// whether or not the fields in the returned <see cref="FieldDoc"/> instances should /// be set by specifying <paramref name="fillFields"/>. /// </summary> protected virtual TopFieldDocs Search(IList <AtomicReaderContext> leaves, Weight weight, FieldDoc after, int nDocs, Sort sort, bool fillFields, bool doDocScores, bool doMaxScore) { // single thread int limit = reader.MaxDoc; if (limit == 0) { limit = 1; } nDocs = Math.Min(nDocs, limit); TopFieldCollector collector = TopFieldCollector.Create(sort, nDocs, after, fillFields, doDocScores, doMaxScore, !weight.ScoresDocsOutOfOrder); Search(leaves, weight, collector); return((TopFieldDocs)collector.GetTopDocs()); }