Esempio n. 1
0
 public TopGroups(TopGroups <TGroupValueType> oldTopGroups, int?totalGroupCount)
 {
     GroupSort            = oldTopGroups.GroupSort;
     WithinGroupSort      = oldTopGroups.WithinGroupSort;
     TotalHitCount        = oldTopGroups.TotalHitCount;
     TotalGroupedHitCount = oldTopGroups.TotalGroupedHitCount;
     Groups          = oldTopGroups.Groups;
     MaxScore        = oldTopGroups.MaxScore;
     TotalGroupCount = totalGroupCount;
 }
Esempio n. 2
0
        /// <summary>
        /// Merges an array of TopGroups, for example obtained from the second-pass
        /// collector across multiple shards. Each TopGroups must have been sorted by the
        /// same groupSort and docSort, and the top groups passed to all second-pass
        /// collectors must be the same.
        ///
        /// <b>NOTE</b>: We can't always compute an exact totalGroupCount.
        /// Documents belonging to a group may occur on more than
        /// one shard and thus the merged totalGroupCount can be
        /// higher than the actual totalGroupCount. In this case the
        /// totalGroupCount represents a upper bound. If the documents
        /// of one group do only reside in one shard then the
        /// totalGroupCount is exact.
        ///
        /// <b>NOTE</b>: the topDocs in each GroupDocs is actually
        /// an instance of TopDocsAndShards
        /// </summary>
        public static TopGroups <T> Merge <T>(TopGroups <T>[] shardGroups, Sort groupSort, Sort docSort, int docOffset, int docTopN, ScoreMergeMode scoreMergeMode)
        {
            //System.out.println("TopGroups.merge");

            if (shardGroups.Length == 0)
            {
                return(null);
            }

            int totalHitCount        = 0;
            int totalGroupedHitCount = 0;
            // Optionally merge the totalGroupCount.
            int?totalGroupCount = null;

            int numGroups = shardGroups[0].Groups.Length;

            foreach (var shard in shardGroups)
            {
                if (numGroups != shard.Groups.Length)
                {
                    throw new ArgumentException("number of groups differs across shards; you must pass same top groups to all shards' second-pass collector");
                }
                totalHitCount        += shard.TotalHitCount;
                totalGroupedHitCount += shard.TotalGroupedHitCount;
                if (shard.TotalGroupCount != null)
                {
                    if (totalGroupCount == null)
                    {
                        totalGroupCount = 0;
                    }

                    totalGroupCount += shard.TotalGroupCount;
                }
            }

            var mergedGroupDocs = new GroupDocs <T> [numGroups];

            TopDocs[] shardTopDocs  = new TopDocs[shardGroups.Length];
            float     totalMaxScore = float.MinValue;

            for (int groupIDX = 0; groupIDX < numGroups; groupIDX++)
            {
                T groupValue = shardGroups[0].Groups[groupIDX].GroupValue;
                //System.out.println("  merge groupValue=" + groupValue + " sortValues=" + Arrays.toString(shardGroups[0].groups[groupIDX].groupSortValues));
                float  maxScore  = float.MinValue;
                int    totalHits = 0;
                double scoreSum  = 0.0;
                for (int shardIdx = 0; shardIdx < shardGroups.Length; shardIdx++)
                {
                    //System.out.println("    shard=" + shardIDX);
                    TopGroups <T> shard          = shardGroups[shardIdx];
                    var           shardGroupDocs = shard.Groups[groupIDX];
                    if (groupValue == null)
                    {
                        if (shardGroupDocs.GroupValue != null)
                        {
                            throw new ArgumentException("group values differ across shards; you must pass same top groups to all shards' second-pass collector");
                        }
                    }
                    else if (!groupValue.Equals(shardGroupDocs.GroupValue))
                    {
                        throw new ArgumentException("group values differ across shards; you must pass same top groups to all shards' second-pass collector");
                    }

                    /*
                     * for(ScoreDoc sd : shardGroupDocs.scoreDocs) {
                     * System.out.println("      doc=" + sd.doc);
                     * }
                     */

                    shardTopDocs[shardIdx] = new TopDocs(shardGroupDocs.TotalHits, shardGroupDocs.ScoreDocs, shardGroupDocs.MaxScore);
                    maxScore   = Math.Max(maxScore, shardGroupDocs.MaxScore);
                    totalHits += shardGroupDocs.TotalHits;
                    scoreSum  += shardGroupDocs.Score;
                }

                TopDocs mergedTopDocs = TopDocs.Merge(docSort, docOffset + docTopN, shardTopDocs);

                // Slice;
                ScoreDoc[] mergedScoreDocs;
                if (docOffset == 0)
                {
                    mergedScoreDocs = mergedTopDocs.ScoreDocs;
                }
                else if (docOffset >= mergedTopDocs.ScoreDocs.Length)
                {
                    mergedScoreDocs = new ScoreDoc[0];
                }
                else
                {
                    mergedScoreDocs = new ScoreDoc[mergedTopDocs.ScoreDocs.Length - docOffset];
                    Array.Copy(mergedTopDocs.ScoreDocs, docOffset, mergedScoreDocs, 0, mergedTopDocs.ScoreDocs.Length - docOffset);
                }

                float groupScore;
                switch (scoreMergeMode)
                {
                case ScoreMergeMode.None:
                    groupScore = float.NaN;
                    break;

                case ScoreMergeMode.Avg:
                    if (totalHits > 0)
                    {
                        groupScore = (float)(scoreSum / totalHits);
                    }
                    else
                    {
                        groupScore = float.NaN;
                    }
                    break;

                case ScoreMergeMode.Total:
                    groupScore = (float)scoreSum;
                    break;

                default:
                    throw new ArgumentException("can't handle ScoreMergeMode " + scoreMergeMode);
                }

                //System.out.println("SHARDS=" + Arrays.toString(mergedTopDocs.shardIndex));
                mergedGroupDocs[groupIDX] = new GroupDocs <T>(groupScore, maxScore, totalHits, mergedScoreDocs, groupValue, shardGroups[0].Groups[groupIDX].GroupSortValues);
                totalMaxScore             = Math.Max(totalMaxScore, maxScore);
            }

            if (totalGroupCount != null)
            {
                var result = new TopGroups <T>(groupSort.GetSort(), docSort == null ? null : docSort.GetSort(), totalHitCount, totalGroupedHitCount, mergedGroupDocs, totalMaxScore);
                return(new TopGroups <T>(result, totalGroupCount));
            }

            return(new TopGroups <T>(groupSort.GetSort(), docSort == null ? null : docSort.GetSort(), totalHitCount, totalGroupedHitCount, mergedGroupDocs, totalMaxScore));
        }