示例#1
0
            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;
                }
            }
示例#2
0
            public TopDocs Call()
            {
                TopDocs docs = searcher.Search(Arrays.AsList(slice.Leaves), weight, after, nDocs);

                ScoreDoc[] scoreDocs = docs.ScoreDocs;
                //it would be so nice if we had a thread-safe insert
                @lock.Lock();
                try
                {
                    for (int j = 0; j < scoreDocs.Length; j++) // merge scoreDocs into hq
                    {
                        ScoreDoc scoreDoc = scoreDocs[j];
                        if (scoreDoc == hq.InsertWithOverflow(scoreDoc))
                        {
                            break;
                        }
                    }
                }
                finally
                {
                    @lock.Unlock();
                }
                return(docs);
            }
示例#3
0
 public SearcherCallableNoSort(ReentrantLock @lock, IndexSearcher searcher, LeafSlice slice, Weight weight, ScoreDoc after, int nDocs, HitQueue hq)
 {
     this.@lock    = @lock;
     this.searcher = searcher;
     this.weight   = weight;
     this.after    = after;
     this.nDocs    = nDocs;
     this.hq       = hq;
     this.slice    = slice;
 }
示例#4
0
        /// <summary>
        /// Expert: Low-level search implementation.  Finds the top <code>n</code>
        /// hits for <c>query</c>.
        ///
        /// <para/>Applications should usually call <see cref="IndexSearcher.Search(Query,int)"/> or
        /// <see cref="IndexSearcher.Search(Query,Filter,int)"/> instead. </summary>
        /// <exception cref="BooleanQuery.TooManyClausesException"> If a query would exceed
        ///         <see cref="BooleanQuery.MaxClauseCount"/> clauses. </exception>
        protected virtual TopDocs Search(IList <AtomicReaderContext> leaves, Weight weight, ScoreDoc after, int nDocs)
        {
            // single thread
            int limit = reader.MaxDoc;

            if (limit == 0)
            {
                limit = 1;
            }
            nDocs = Math.Min(nDocs, limit);
            TopScoreDocCollector collector = TopScoreDocCollector.Create(nDocs, after, !weight.ScoresDocsOutOfOrder);

            Search(leaves, weight, collector);
            return(collector.GetTopDocs());
        }
示例#5
0
 /// <summary>
 /// Finds the top <paramref name="n"/>
 /// hits for <paramref name="query"/>, applying <paramref name="filter"/> if non-null,
 /// where all results are after a previous result (<paramref name="after"/>).
 /// <para/>
 /// By passing the bottom result from a previous page as <paramref name="after"/>,
 /// this method can be used for efficient 'deep-paging' across potentially
 /// large result sets.
 /// </summary>
 /// <exception cref="BooleanQuery.TooManyClausesException"> If a query would exceed
 ///         <see cref="BooleanQuery.MaxClauseCount"/> clauses. </exception>
 public virtual TopDocs SearchAfter(ScoreDoc after, Query query, Filter filter, int n)
 {
     return(Search(CreateNormalizedWeight(WrapFilter(query, filter)), after, n));
 }
示例#6
0
 /// <summary>
 /// Finds the top <paramref name="n"/>
 /// hits for top <paramref name="query"/> where all results are after a previous
 /// result (top <paramref name="after"/>).
 /// <para/>
 /// By passing the bottom result from a previous page as <paramref name="after"/>,
 /// this method can be used for efficient 'deep-paging' across potentially
 /// large result sets.
 /// </summary>
 /// <exception cref="BooleanQuery.TooManyClausesException"> If a query would exceed
 ///         <see cref="BooleanQuery.MaxClauseCount"/> clauses. </exception>
 public virtual TopDocs SearchAfter(ScoreDoc after, Query query, int n)
 {
     return(Search(CreateNormalizedWeight(query), after, n));
 }
示例#7
0
 internal InOrderPagingScoreDocCollector(ScoreDoc after, int numHits)
     : base(numHits)
 {
     this.after = after;
 }
示例#8
0
        public override TopDocs Rescore(IndexSearcher searcher, TopDocs firstPassTopDocs, int topN)
        {
            ScoreDoc[] hits = (ScoreDoc[])firstPassTopDocs.ScoreDocs.Clone();
            Array.Sort(hits, Comparer <ScoreDoc> .Create((a, b) => a.Doc - b.Doc));

            IList <AtomicReaderContext> leaves = searcher.IndexReader.Leaves;

            Weight weight = searcher.CreateNormalizedWeight(query);

            // Now merge sort docIDs from hits, with reader's leaves:
            int    hitUpto    = 0;
            int    readerUpto = -1;
            int    endDoc     = 0;
            int    docBase    = 0;
            Scorer scorer     = null;

            while (hitUpto < hits.Length)
            {
                ScoreDoc            hit           = hits[hitUpto];
                int                 docID         = hit.Doc;
                AtomicReaderContext readerContext = null;
                while (docID >= endDoc)
                {
                    readerUpto++;
                    readerContext = leaves[readerUpto];
                    endDoc        = readerContext.DocBase + readerContext.Reader.MaxDoc;
                }

                if (readerContext != null)
                {
                    // We advanced to another segment:
                    docBase = readerContext.DocBase;
                    scorer  = weight.GetScorer(readerContext, null);
                }

                int targetDoc = docID - docBase;
                int actualDoc = scorer.DocID;
                if (actualDoc < targetDoc)
                {
                    actualDoc = scorer.Advance(targetDoc);
                }

                if (actualDoc == targetDoc)
                {
                    // Query did match this doc:
                    hit.Score = Combine(hit.Score, true, scorer.GetScore());
                }
                else
                {
                    // Query did not match this doc:
                    if (Debugging.AssertsEnabled)
                    {
                        Debugging.Assert(actualDoc > targetDoc);
                    }
                    hit.Score = Combine(hit.Score, false, 0.0f);
                }

                hitUpto++;
            }

            // TODO: we should do a partial sort (of only topN)
            // instead, but typically the number of hits is
            // smallish:
            Array.Sort(hits, Comparer <ScoreDoc> .Create((a, b) =>
            {
                // Sort by score descending, then docID ascending:
                if (a.Score > b.Score)
                {
                    return(-1);
                }
                else if (a.Score < b.Score)
                {
                    return(1);
                }
                else
                {
                    // this subtraction can't overflow int
                    // because docIDs are >= 0:
                    return(a.Doc - b.Doc);
                }
            }));

            if (topN < hits.Length)
            {
                ScoreDoc[] subset = new ScoreDoc[topN];
                Array.Copy(hits, 0, subset, 0, topN);
                hits = subset;
            }

            return(new TopDocs(firstPassTopDocs.TotalHits, hits, hits[0].Score));
        }
示例#9
0
        public static TopDocs Merge(Sort sort, int start, int size, TopDocs[] shardHits)
        {
            Util.PriorityQueue <ShardRef> queue;
            if (sort == null)
            {
                queue = new ScoreMergeSortQueue(shardHits);
            }
            else
            {
                queue = new MergeSortQueue(sort, shardHits);
            }

            int   totalHitCount = 0;
            int   availHitCount = 0;
            float maxScore      = float.MinValue;

            for (int shardIDX = 0; shardIDX < shardHits.Length; shardIDX++)
            {
                TopDocs shard = shardHits[shardIDX];
                // totalHits can be non-zero even if no hits were
                // collected, when searchAfter was used:
                totalHitCount += shard.TotalHits;
                if (shard.ScoreDocs != null && shard.ScoreDocs.Length > 0)
                {
                    availHitCount += shard.ScoreDocs.Length;
                    queue.Add(new ShardRef(shardIDX));
                    maxScore = Math.Max(maxScore, shard.MaxScore);
                    //System.out.println("  maxScore now " + maxScore + " vs " + shard.getMaxScore());
                }
            }

            if (availHitCount == 0)
            {
                maxScore = float.NaN;
            }

            ScoreDoc[] hits;
            if (availHitCount <= start)
            {
                hits = new ScoreDoc[0];
            }
            else
            {
                hits = new ScoreDoc[Math.Min(size, availHitCount - start)];
                int requestedResultWindow = start + size;
                int numIterOnHits         = Math.Min(availHitCount, requestedResultWindow);
                int hitUpto = 0;
                while (hitUpto < numIterOnHits)
                {
                    Debug.Assert(queue.Count > 0);
                    ShardRef @ref = queue.Pop();
                    ScoreDoc hit  = shardHits[@ref.ShardIndex].ScoreDocs[@ref.HitIndex++];
                    hit.ShardIndex = @ref.ShardIndex;
                    if (hitUpto >= start)
                    {
                        hits[hitUpto - start] = hit;
                    }

                    //System.out.println("  hitUpto=" + hitUpto);
                    //System.out.println("    doc=" + hits[hitUpto].doc + " score=" + hits[hitUpto].score);

                    hitUpto++;

                    if (@ref.HitIndex < shardHits[@ref.ShardIndex].ScoreDocs.Length)
                    {
                        // Not done with this these TopDocs yet:
                        queue.Add(@ref);
                    }
                }
            }

            if (sort == null)
            {
                return(new TopDocs(totalHitCount, hits, maxScore));
            }
            else
            {
                return(new TopFieldDocs(totalHitCount, hits, sort.GetSort(), maxScore));
            }
        }