Expert: A ScoreDoc which also contains information about how to sort the referenced document. In addition to the document number and score, this object contains an array of values for the document from the field(s) used to sort. For example, if the sort criteria was to sort by fields "a", "b" then "c", the fields object array will have three elements, corresponding respectively to the term values for the document in fields "a", "b" and "c". The class of each element in the array will be either Integer, Float or String depending on the type of values in the terms of each field.

Created: Feb 11, 2004 1:23:38 PM @since lucene 1.4

Inheritance: Lucene.Net.Search.ScoreDoc
Beispiel #1
0
        private void  Compare(TopDocs oldHits, TopDocs newHits)
        {
            Assert.AreEqual(oldHits.totalHits, newHits.totalHits);
            Assert.AreEqual(oldHits.scoreDocs.Length, newHits.scoreDocs.Length);
            ScoreDoc[] oldDocs = oldHits.scoreDocs;
            ScoreDoc[] newDocs = newHits.scoreDocs;

            for (int i = 0; i < oldDocs.Length; i++)
            {
                if (oldDocs[i] is FieldDoc)
                {
                    System.Diagnostics.Debug.Assert(newDocs[i] is FieldDoc);
                    FieldDoc oldHit = (FieldDoc)oldDocs[i];
                    FieldDoc newHit = (FieldDoc)newDocs[i];
                    Assert.AreEqual(oldHit.doc, newHit.doc, "hit " + i + " of " + oldDocs.Length + " differs: oldDoc=" + oldHit.doc + " vs newDoc=" + newHit.doc + " oldFields=" + _TestUtil.ArrayToString(oldHit.fields) + " newFields=" + _TestUtil.ArrayToString(newHit.fields));

                    Assert.AreEqual(oldHit.score, newHit.score, 0.00001);
                    Assert.IsTrue(SupportClass.CollectionsHelper.Equals(oldHit.fields, newHit.fields));
                }
                else
                {
                    ScoreDoc oldHit = oldDocs[i];
                    ScoreDoc newHit = newDocs[i];
                    Assert.AreEqual(oldHit.doc, newHit.doc);
                    Assert.AreEqual(oldHit.score, newHit.score, 0.00001);
                }
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        override public void  Run()
        {
            try
            {
                docs = (sort == null)?searchable.Search(weight, filter, nDocs):searchable.Search(weight, filter, nDocs, sort);
            }
            // Store the IOException for later use by the caller of this thread
            catch (System.Exception e)
            {
                this.ioe = e;
            }
            if (this.ioe == null)
            {
                // if we are sorting by fields, we need to tell the field sorted hit queue
                // the actual type of fields, in case the original list contained AUTO.
                // if the searchable returns null for fields, we'll have problems.
                if (sort != null)
                {
                    TopFieldDocs docsFields = (TopFieldDocs)docs;
                    // If one of the Sort fields is FIELD_DOC, need to fix its values, so that
                    // it will break ties by doc Id properly. Otherwise, it will compare to
                    // 'relative' doc Ids, that belong to two different searchables.
                    for (int j = 0; j < docsFields.fields.Length; j++)
                    {
                        if (docsFields.fields[j].GetType() == SortField.DOC)
                        {
                            // iterate over the score docs and change their fields value
                            for (int j2 = 0; j2 < docs.ScoreDocs.Length; j2++)
                            {
                                FieldDoc fd = (FieldDoc)docs.ScoreDocs[j2];
                                //DIGY?? No unit test for the line below
                                fd.fields[j] = (System.Int32)(((System.Int32)fd.fields[j]) + starts[i]);
                            }
                            break;
                        }
                    }

                    ((FieldDocSortedHitQueue)hq).SetFields(docsFields.fields);
                }
                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
                    //it would be so nice if we had a thread-safe insert
                    lock (hq)
                    {
                        if (!hq.Insert(scoreDoc))
                        {
                            break;
                        }
                    }                     // no more scores > minScore
                }
            }
        }
Beispiel #4
0
        public override TopFieldDocs Search(Weight weight, Filter filter, int n, Sort sort)
        {
            FieldDocSortedHitQueue hq = null;
            int totalHits             = 0;

            float maxScore = System.Single.NegativeInfinity;

            for (int i = 0; i < searchables.Length; i++)
            {
                // search each searcher
                TopFieldDocs docs = searchables[i].Search(weight, filter, n, sort);
                // If one of the Sort fields is FIELD_DOC, need to fix its values, so that
                // it will break ties by doc Id properly. Otherwise, it will compare to
                // 'relative' doc Ids, that belong to two different searchers.
                for (int j = 0; j < docs.fields.Length; j++)
                {
                    if (docs.fields[j].GetType() == SortField.DOC)
                    {
                        // iterate over the score docs and change their fields value
                        for (int j2 = 0; j2 < docs.scoreDocs.Length; j2++)
                        {
                            FieldDoc fd = (FieldDoc)docs.scoreDocs[j2];
                            fd.fields[j] = (System.Int32)(((System.Int32)fd.fields[j]) + starts[i]);
                        }
                        break;
                    }
                }
                if (hq == null)
                {
                    hq = new FieldDocSortedHitQueue(docs.fields, n);
                }
                totalHits += docs.totalHits;                 // update totalHits
                maxScore   = System.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[] scoreDocs2 = new ScoreDoc[hq.Size()];
            for (int i = hq.Size() - 1; i >= 0; i--)
            {
                // put docs in array
                scoreDocs2[i] = (ScoreDoc)hq.Pop();
            }

            return(new TopFieldDocs(totalHits, scoreDocs2, hq.GetFields(), maxScore));
        }
        /// <summary> Given a FieldDoc object, stores the values used
        /// to sort the given document.  These values are not the raw
        /// values out of the index, but the internal representation
        /// of them.  This is so the given search hit can be collated
        /// by a MultiSearcher with other search hits.
        /// </summary>
        /// <param name="doc"> The FieldDoc to store sort values into.
        /// </param>
        /// <returns>  The same FieldDoc passed in.
        /// </returns>
        /// <seealso cref="Searchable.Search(Weight,Filter,int,Sort)">
        /// </seealso>
        internal virtual FieldDoc FillFields(FieldDoc doc)
        {
            int n = comparators.Length;

            System.IComparable[] fields = new System.IComparable[n];
            for (int i = 0; i < n; ++i)
            {
                fields[i] = comparators[i].SortValue(doc);
            }
            doc.fields = fields;
            //if (maxscore > 1.0f) doc.score /= maxscore;   // normalize scores
            return(doc);
        }
Beispiel #6
0
 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;
 }
Beispiel #7
0
        /// <summary>
        /// Just like <seealso cref="#search(Weight, int, Sort, boolean, boolean)"/>, but you choose
        /// whether or not the fields in the returned <seealso cref="FieldDoc"/> instances should
        /// be set by specifying fillFields.
        /// </summary>
        protected internal virtual TopFieldDocs Search(Weight weight, FieldDoc after, int nDocs, Sort sort, bool fillFields, bool doDocScores, bool doMaxScore)
        {
            if (sort == null)
            {
                throw new System.NullReferenceException("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(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 < LeafSlices.Length; i++) // search each leaf slice
                {
                    runner.Submit(new SearcherCallableWithSort(@lock, this, 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.TopDocs();

                return(new TopFieldDocs(totalHits, topDocs.ScoreDocs, topDocs.Fields, topDocs.MaxScore));
            }
        }
Beispiel #8
0
            // 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);
                }
            }
Beispiel #9
0
        /*
         * Only the following callback methods need to be overridden since
         * topDocs(int, int) calls them to return the results.
         */

        protected internal override void  PopulateResults(ScoreDoc[] results, int howMany)
        {
            if (fillFields)
            {
                // avoid casting if unnecessary.
                FieldValueHitQueue queue = (FieldValueHitQueue)pq;
                for (int i = howMany - 1; i >= 0; i--)
                {
                    results[i] = queue.FillFields((Entry)queue.Pop());
                }
            }
            else
            {
                for (int i = howMany - 1; i >= 0; i--)
                {
                    Entry entry = (Entry)pq.Pop();
                    results[i] = new FieldDoc(entry.docID, entry.score);
                }
            }
        }
		// javadoc inherited
		public override void  Collect(int doc, float score)
		{
			if (score > 0.0f)
			{
				totalHits++;
				if (reusableFD == null)
					reusableFD = new FieldDoc(doc, score);
				else
				{
					// Whereas TopScoreDocCollector can skip this if the
					// score is not competitive, we cannot because the
					// comparators in the FieldSortedHitQueue.lessThan
					// aren't in general congruent with "higher score
					// wins"
					reusableFD.score = score;
					reusableFD.doc = doc;
				}
				reusableFD = (FieldDoc) hq.InsertWithOverflow(reusableFD);
			}
		}
Beispiel #11
0
 // javadoc inherited
 public override void  Collect(int doc, float score)
 {
     if (score > 0.0f)
     {
         totalHits++;
         if (reusableFD == null)
         {
             reusableFD = new FieldDoc(doc, score);
         }
         else
         {
             // Whereas TopDocCollector can skip this if the
             // score is not competitive, we cannot because the
             // comparators in the FieldSortedHitQueue.lessThan
             // aren't in general congruent with "higher score
             // wins"
             reusableFD.score = score;
             reusableFD.doc   = doc;
         }
         reusableFD = (FieldDoc)hq.InsertWithOverflow(reusableFD);
     }
 }
Beispiel #12
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;
                }
            }
 // The signature of this method takes a FieldDoc in order to avoid
 // the unneeded cast to retrieve the score.
 // inherit javadoc
 public virtual bool Insert(FieldDoc fdoc)
 {
     maxscore = System.Math.Max(maxscore, fdoc.score);
     return(base.Insert(fdoc));
 }
Beispiel #14
0
 // Update maxscore.
 private void UpdateMaxScore(FieldDoc fdoc)
 {
     maxscore = System.Math.Max(maxscore, fdoc.score);
 }
Beispiel #15
0
 /// <summary> Given a FieldDoc object, stores the values used
 /// to sort the given document.  These values are not the raw
 /// values out of the index, but the internal representation
 /// of them.  This is so the given search hit can be collated
 /// by a MultiSearcher with other search hits.
 /// </summary>
 /// <param name="doc"> The FieldDoc to store sort values into.
 /// </param>
 /// <returns>  The same FieldDoc passed in.
 /// </returns>
 /// <seealso cref="Searchable.Search(Weight,Filter,int,Sort)">
 /// </seealso>
 internal virtual FieldDoc FillFields(FieldDoc doc)
 {
     int n = comparators.Length;
     System.IComparable[] fields = new System.IComparable[n];
     for (int i = 0; i < n; ++i)
         fields[i] = comparators[i].SortValue(doc);
     doc.fields = fields;
     //if (maxscore > 1.0f) doc.score /= maxscore;   // normalize scores
     return doc;
 }
 // The signature of this method takes a FieldDoc in order to avoid
 // the unneeded cast to retrieve the score.
 // inherit javadoc
 public virtual bool Insert(FieldDoc fdoc)
 {
     maxscore = System.Math.Max(maxscore, fdoc.score);
     return base.Insert(fdoc);
 }
 // The signature of this method takes a FieldDoc in order to avoid
 // the unneeded cast to retrieve the score.
 // inherit javadoc
 public virtual bool Insert(FieldDoc fdoc)
 {
     UpdateMaxScore(fdoc);
     return(base.Insert(fdoc));
 }
Beispiel #18
0
 /*
 * Only the following callback methods need to be overridden since
 * topDocs(int, int) calls them to return the results.
 */
 protected internal override void PopulateResults(ScoreDoc[] results, int howMany)
 {
     if (fillFields)
     {
         // avoid casting if unnecessary.
         FieldValueHitQueue queue = (FieldValueHitQueue) pq;
         for (int i = howMany - 1; i >= 0; i--)
         {
             results[i] = queue.FillFields((Entry) queue.Pop());
         }
     }
     else
     {
         for (int i = howMany - 1; i >= 0; i--)
         {
             Entry entry = (Entry) pq.Pop();
             results[i] = new FieldDoc(entry.docID, entry.score);
         }
     }
 }
Beispiel #19
0
        /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
        /// <param name="a">ScoreDoc
        /// </param>
        /// <param name="b">ScoreDoc
        /// </param>
        /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
        /// </returns>
        public override bool LessThan(System.Object a, System.Object b)
        {
            FieldDoc docA = (FieldDoc)a;
            FieldDoc docB = (FieldDoc)b;
            int      n    = fields.Length;
            int      c    = 0;

            for (int i = 0; i < n && c == 0; ++i)
            {
                int type = fields[i].GetSortType();
                switch (type)
                {
                case SortField.SCORE:
                    float r1 = (float)((System.Single)docA.fields[i]);
                    float r2 = (float)((System.Single)docB.fields[i]);
                    if (r1 > r2)
                    {
                        c = -1;
                    }
                    if (r1 < r2)
                    {
                        c = 1;
                    }
                    break;

                case SortField.DOC:
                case SortField.INT:
                    int i1 = ((System.Int32)docA.fields[i]);
                    int i2 = ((System.Int32)docB.fields[i]);
                    if (i1 < i2)
                    {
                        c = -1;
                    }
                    if (i1 > i2)
                    {
                        c = 1;
                    }
                    break;

                case SortField.STRING:
                    System.String s1 = (System.String)docA.fields[i];
                    System.String s2 = (System.String)docB.fields[i];
                    // null values need to be sorted first, because of how FieldCache.getStringIndex()
                    // works - in that routine, any documents without a value in the given field are
                    // put first.  If both are null, the next SortField is used
                    if (s1 == null)
                    {
                        c = (s2 == null)?0:-1;
                    }
                    else if (s2 == null)
                    {
                        c = 1;
                    }
                    //
                    else if (fields[i].GetLocale() == null)
                    {
                        c = String.CompareOrdinal(s1, s2);
                    }
                    else
                    {
                        //UPGRADE_TODO: The equivalent in .NET for method 'java.text.Collator.compare' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
                        c = collators[i].Compare(s1.ToString(), s2.ToString());
                    }
                    break;

                case SortField.FLOAT:
                    //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
                    float f1 = (float)((System.Single)docA.fields[i]);
                    //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
                    float f2 = (float)((System.Single)docB.fields[i]);
                    if (f1 < f2)
                    {
                        c = -1;
                    }
                    if (f1 > f2)
                    {
                        c = 1;
                    }
                    break;

                case SortField.CUSTOM:
                    c = docA.fields[i].CompareTo(docB.fields[i]);
                    break;

                case SortField.AUTO:
                    // we cannot handle this - even if we determine the type of object (Float or
                    // Integer), we don't necessarily know how to compare them (both SCORE and
                    // FLOAT contain floats, but are sorted opposite of each other). Before
                    // we get here, each AUTO should have been replaced with its actual value.
                    throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");

                default:
                    throw new System.SystemException("invalid SortField type: " + type);
                }
                if (fields[i].GetReverse())
                {
                    c = -c;
                }
            }

            // avoid random sort order that could lead to duplicates (bug #31241):
            if (c == 0)
            {
                return(docA.doc > docB.doc);
            }

            return(c > 0);
        }
Beispiel #20
0
 /// <summary>
 /// Search, sorting by <seealso cref="Sort"/>, and computing
 /// drill down and sideways counts.
 /// </summary>
 public virtual DrillSidewaysResult Search(DrillDownQuery query, Filter filter, FieldDoc after, int topN, Sort sort, bool doDocScores, bool doMaxScore)
 {
     if (filter != null)
     {
         query = new DrillDownQuery(config, filter, query);
     }
     if (sort != null)
     {
         int limit = searcher.IndexReader.MaxDoc;
         if (limit == 0)
         {
             limit = 1; // the collector does not alow numHits = 0
         }
         topN = Math.Min(topN, limit);
         TopFieldCollector hitCollector = TopFieldCollector.Create(sort, topN, after, true, doDocScores, doMaxScore, true);
         DrillSidewaysResult r = Search(query, hitCollector);
         return new DrillSidewaysResult(r.Facets, hitCollector.TopDocs());
     }
     else
     {
         return Search(after, query, topN);
     }
 }
Beispiel #21
0
        public virtual void TestRandomStringSort()
        {
            Random random = new Random(Random().Next());

            int               NUM_DOCS  = AtLeast(100);
            Directory         dir       = NewDirectory();
            RandomIndexWriter writer    = new RandomIndexWriter(random, dir, Similarity, TimeZone);
            bool              allowDups = random.NextBoolean();
            HashSet <string>  seen      = new HashSet <string>();
            int               maxLength = TestUtil.NextInt(random, 5, 100);

            if (VERBOSE)
            {
                Console.WriteLine("TEST: NUM_DOCS=" + NUM_DOCS + " maxLength=" + maxLength + " allowDups=" + allowDups);
            }

            int numDocs = 0;
            IList <BytesRef> docValues = new List <BytesRef>();

            // TODO: deletions
            while (numDocs < NUM_DOCS)
            {
                Document doc = new Document();

                // 10% of the time, the document is missing the value:
                BytesRef br;
                if (Random().Next(10) != 7)
                {
                    string s;
                    if (random.NextBoolean())
                    {
                        s = TestUtil.RandomSimpleString(random, maxLength);
                    }
                    else
                    {
                        s = TestUtil.RandomUnicodeString(random, maxLength);
                    }

                    if (!allowDups)
                    {
                        if (seen.Contains(s))
                        {
                            continue;
                        }
                        seen.Add(s);
                    }

                    if (VERBOSE)
                    {
                        Console.WriteLine("  " + numDocs + ": s=" + s);
                    }

                    br = new BytesRef(s);
                    if (DefaultCodecSupportsDocValues())
                    {
                        doc.Add(new SortedDocValuesField("stringdv", br));
                        doc.Add(new NumericDocValuesField("id", numDocs));
                    }
                    else
                    {
                        doc.Add(NewStringField("id", Convert.ToString(numDocs), Field.Store.NO));
                    }
                    doc.Add(NewStringField("string", s, Field.Store.NO));
                    docValues.Add(br);
                }
                else
                {
                    br = null;
                    if (VERBOSE)
                    {
                        Console.WriteLine("  " + numDocs + ": <missing>");
                    }
                    docValues.Add(null);
                    if (DefaultCodecSupportsDocValues())
                    {
                        doc.Add(new NumericDocValuesField("id", numDocs));
                    }
                    else
                    {
                        doc.Add(NewStringField("id", Convert.ToString(numDocs), Field.Store.NO));
                    }
                }

                doc.Add(new StoredField("id", numDocs));
                writer.AddDocument(doc);
                numDocs++;

                if (random.Next(40) == 17)
                {
                    // force flush
                    writer.Reader.Dispose();
                }
            }

            IndexReader r = writer.Reader;

            writer.Dispose();
            if (VERBOSE)
            {
                Console.WriteLine("  reader=" + r);
            }

            IndexSearcher idxS  = NewSearcher(r, false, Similarity);
            int           ITERS = AtLeast(100);

            for (int iter = 0; iter < ITERS; iter++)
            {
                bool reverse = random.NextBoolean();

                TopFieldDocs hits;
                SortField    sf;
                bool         sortMissingLast;
                bool         missingIsNull;
                if (DefaultCodecSupportsDocValues() && random.NextBoolean())
                {
                    sf = new SortField("stringdv", SortField.Type_e.STRING, reverse);
                    // Can only use sort missing if the DVFormat
                    // supports docsWithField:
                    sortMissingLast = DefaultCodecSupportsDocsWithField() && Random().NextBoolean();
                    missingIsNull   = DefaultCodecSupportsDocsWithField();
                }
                else
                {
                    sf = new SortField("string", SortField.Type_e.STRING, reverse);
                    sortMissingLast = Random().NextBoolean();
                    missingIsNull   = true;
                }
                if (sortMissingLast)
                {
                    sf.MissingValue = SortField.STRING_LAST;
                }

                Sort sort;
                if (random.NextBoolean())
                {
                    sort = new Sort(sf);
                }
                else
                {
                    sort = new Sort(sf, SortField.FIELD_DOC);
                }
                int          hitCount  = TestUtil.NextInt(random, 1, r.MaxDoc + 20);
                RandomFilter f         = new RandomFilter(random, (float)random.NextDouble(), docValues);
                int          queryType = random.Next(3);
                if (queryType == 0)
                {
                    // force out of order
                    BooleanQuery bq = new BooleanQuery();
                    // Add a Query with SHOULD, since bw.Scorer() returns BooleanScorer2
                    // which delegates to BS if there are no mandatory clauses.
                    bq.Add(new MatchAllDocsQuery(), Occur.SHOULD);
                    // Set minNrShouldMatch to 1 so that BQ will not optimize rewrite to return
                    // the clause instead of BQ.
                    bq.MinimumNumberShouldMatch = 1;
                    hits = idxS.Search(bq, f, hitCount, sort, random.NextBoolean(), random.NextBoolean());
                }
                else if (queryType == 1)
                {
                    hits = idxS.Search(new ConstantScoreQuery(f), null, hitCount, sort, random.NextBoolean(), random.NextBoolean());
                }
                else
                {
                    hits = idxS.Search(new MatchAllDocsQuery(), f, hitCount, sort, random.NextBoolean(), random.NextBoolean());
                }

                if (VERBOSE)
                {
                    Console.WriteLine("\nTEST: iter=" + iter + " " + hits.TotalHits + " hits; topN=" + hitCount + "; reverse=" + reverse + "; sortMissingLast=" + sortMissingLast + " sort=" + sort);
                }

                // Compute expected results:
                var expected = f.MatchValues.ToList();
                expected.Sort(new ComparatorAnonymousInnerClassHelper(this, sortMissingLast));
                if (reverse)
                {
                    expected.Reverse();
                }

                if (VERBOSE)
                {
                    Console.WriteLine("  expected:");
                    for (int idx = 0; idx < expected.Count; idx++)
                    {
                        BytesRef br = expected[idx];
                        if (br == null && missingIsNull == false)
                        {
                            br = new BytesRef();
                        }
                        Console.WriteLine("    " + idx + ": " + (br == null ? "<missing>" : br.Utf8ToString()));
                        if (idx == hitCount - 1)
                        {
                            break;
                        }
                    }
                }

                if (VERBOSE)
                {
                    Console.WriteLine("  actual:");
                    for (int hitIDX = 0; hitIDX < hits.ScoreDocs.Length; hitIDX++)
                    {
                        FieldDoc fd = (FieldDoc)hits.ScoreDocs[hitIDX];
                        BytesRef br = (BytesRef)fd.Fields[0];

                        Console.WriteLine("    " + hitIDX + ": " + (br == null ? "<missing>" : br.Utf8ToString()) + " id=" + idxS.Doc(fd.Doc).Get("id"));
                    }
                }
                for (int hitIDX = 0; hitIDX < hits.ScoreDocs.Length; hitIDX++)
                {
                    FieldDoc fd = (FieldDoc)hits.ScoreDocs[hitIDX];
                    BytesRef br = expected[hitIDX];
                    if (br == null && missingIsNull == false)
                    {
                        br = new BytesRef();
                    }

                    // Normally, the old codecs (that don't support
                    // docsWithField via doc values) will always return
                    // an empty BytesRef for the missing case; however,
                    // if all docs in a given segment were missing, in
                    // that case it will return null!  So we must map
                    // null here, too:
                    BytesRef br2 = (BytesRef)fd.Fields[0];
                    if (br2 == null && missingIsNull == false)
                    {
                        br2 = new BytesRef();
                    }

                    Assert.AreEqual(br, br2, "hit=" + hitIDX + " has wrong sort value");
                }
            }

            r.Dispose();
            dir.Dispose();
        }
 // Update maxscore.
 private void  UpdateMaxScore(FieldDoc fdoc)
 {
     maxscore = System.Math.Max(maxscore, fdoc.score);
 }
        /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
        /// <param name="a">ScoreDoc
        /// </param>
        /// <param name="b">ScoreDoc
        /// </param>
        /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
        /// </returns>
        public override bool LessThan(System.Object a, System.Object b)
        {
            FieldDoc docA = (FieldDoc)a;
            FieldDoc docB = (FieldDoc)b;
            int      n    = fields.Length;
            int      c    = 0;

            for (int i = 0; i < n && c == 0; ++i)
            {
                int type = fields[i].GetType();
                switch (type)
                {
                case SortField.SCORE:  {
                    float r1 = (float)((System.Single)docA.fields[i]);
                    float r2 = (float)((System.Single)docB.fields[i]);
                    if (r1 > r2)
                    {
                        c = -1;
                    }
                    if (r1 < r2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.DOC:
                case SortField.INT:  {
                    int i1 = ((System.Int32)docA.fields[i]);
                    int i2 = ((System.Int32)docB.fields[i]);
                    if (i1 < i2)
                    {
                        c = -1;
                    }
                    if (i1 > i2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.LONG:  {
                    long l1 = (long)((System.Int64)docA.fields[i]);
                    long l2 = (long)((System.Int64)docB.fields[i]);
                    if (l1 < l2)
                    {
                        c = -1;
                    }
                    if (l1 > l2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.STRING:  {
                    System.String s1 = (System.String)docA.fields[i];
                    System.String s2 = (System.String)docB.fields[i];
                    // null values need to be sorted first, because of how FieldCache.getStringIndex()
                    // works - in that routine, any documents without a value in the given field are
                    // put first.  If both are null, the next SortField is used
                    if (s1 == null)
                    {
                        c = (s2 == null)?0:-1;
                    }
                    else if (s2 == null)
                    {
                        c = 1;
                    }
                    //
                    else if (fields[i].GetLocale() == null)
                    {
                        c = String.CompareOrdinal(s1, s2);
                    }
                    else
                    {
                        c = collators[i].Compare(s1.ToString(), s2.ToString());
                    }
                    break;
                }

                case SortField.FLOAT:  {
                    float f1 = (float)((System.Single)docA.fields[i]);
                    float f2 = (float)((System.Single)docB.fields[i]);
                    if (f1 < f2)
                    {
                        c = -1;
                    }
                    if (f1 > f2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.DOUBLE:  {
                    double d1 = ((System.Double)docA.fields[i]);
                    double d2 = ((System.Double)docB.fields[i]);
                    if (d1 < d2)
                    {
                        c = -1;
                    }
                    if (d1 > d2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.BYTE:  {
                    int i1 = (sbyte)((System.SByte)docA.fields[i]);
                    int i2 = (sbyte)((System.SByte)docB.fields[i]);
                    if (i1 < i2)
                    {
                        c = -1;
                    }
                    if (i1 > i2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.SHORT:  {
                    int i1 = (short)((System.Int16)docA.fields[i]);
                    int i2 = (short)((System.Int16)docB.fields[i]);
                    if (i1 < i2)
                    {
                        c = -1;
                    }
                    if (i1 > i2)
                    {
                        c = 1;
                    }
                    break;
                }

                case SortField.CUSTOM:  {
                    c = docA.fields[i].CompareTo(docB.fields[i]);
                    break;
                }

                case SortField.AUTO:  {
                    // we cannot handle this - even if we determine the type of object (Float or
                    // Integer), we don't necessarily know how to compare them (both SCORE and
                    // FLOAT contain floats, but are sorted opposite of each other). Before
                    // we get here, each AUTO should have been replaced with its actual value.
                    throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
                }

                default:  {
                    throw new System.SystemException("invalid SortField type: " + type);
                }
                }
                if (fields[i].GetReverse())
                {
                    c = -c;
                }
            }

            // avoid random sort order that could lead to duplicates (bug #31241):
            if (c == 0)
            {
                return(docA.doc > docB.doc);
            }

            return(c > 0);
        }
Beispiel #24
0
        /// <summary>
        /// Just like <seealso cref="#search(Weight, int, Sort, boolean, boolean)"/>, but you choose
        /// whether or not the fields in the returned <seealso cref="FieldDoc"/> instances should
        /// be set by specifying fillFields.
        /// </summary>
        protected internal 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.TopDocs());
        }
Beispiel #25
0
 // The signature of this method takes a FieldDoc in order to avoid
 // the unneeded cast to retrieve the score.
 // inherit javadoc
 public virtual bool Insert(FieldDoc fdoc)
 {
     UpdateMaxScore(fdoc);
     return base.Insert(fdoc);
 }