public override FieldComparator NewComparator(string fieldname, int numHits, int sortPos, bool reversed) { // we keep parallel slots: the parent ids and the child ids int[] parentSlots = new int[numHits]; int[] childSlots = new int[numHits]; SortField[] parentFields = parentSort.GetSort(); int[] parentReverseMul = new int[parentFields.Length]; FieldComparator[] parentComparators = new FieldComparator[parentFields.Length]; for (int i = 0; i < parentFields.Length; i++) { parentReverseMul[i] = parentFields[i].Reverse ? -1 : 1; parentComparators[i] = parentFields[i].GetComparator(1, i); } SortField[] childFields = childSort.GetSort(); int[] childReverseMul = new int[childFields.Length]; FieldComparator[] childComparators = new FieldComparator[childFields.Length]; for (int i = 0; i < childFields.Length; i++) { childReverseMul[i] = childFields[i].Reverse ? -1 : 1; childComparators[i] = childFields[i].GetComparator(1, i); } // NOTE: we could return parent ID as value but really our sort "value" is more complex... // So we throw UOE for now. At the moment you really should only use this at indexing time. return(new FieldComparatorAnonymousInnerClassHelper(this, parentSlots, childSlots, parentReverseMul, parentComparators, childReverseMul, childComparators)); }
private ToParentBlockJoinFieldComparator(FieldComparator wrappedComparator, Filter parentFilter, Filter childFilter, int spareSlot) { _wrappedComparator = wrappedComparator; _parentFilter = parentFilter; _childFilter = childFilter; _spareSlot = spareSlot; }
public int Compare(ICollectedSearchGroup o1, ICollectedSearchGroup o2) { for (int compIDX = 0; ; compIDX++) { FieldComparator fc = outerInstance.comparators[compIDX]; int c = outerInstance.reversed[compIDX] * fc.Compare(o1.ComparatorSlot, o2.ComparatorSlot); if (c != 0) { return(c); } else if (compIDX == outerInstance.compIDXEnd) { return(o1.TopDoc - o2.TopDoc); } } }
/// <summary> /// Returns a mapping from the old document ID to its new location in the /// sorted index. Implementations can use the auxiliary /// <see cref="Sort(int, DocComparator)"/> to compute the old-to-new permutation /// given a list of documents and their corresponding values. /// <para> /// A return value of <c>null</c> is allowed and means that /// <c>reader</c> is already sorted. /// </para> /// <para> /// <b>NOTE:</b> deleted documents are expected to appear in the mapping as /// well, they will however be marked as deleted in the sorted view. /// </para> /// </summary> internal DocMap Sort(AtomicReader reader) { SortField[] fields = sort_Renamed.GetSort(); int[] reverseMul = new int[fields.Length]; FieldComparator[] comparators = new FieldComparator[fields.Length]; for (int i = 0; i < fields.Length; i++) { reverseMul[i] = fields[i].Reverse ? -1 : 1; comparators[i] = fields[i].GetComparator(1, i); comparators[i].SetNextReader(reader.AtomicContext); comparators[i].Scorer = FAKESCORER; } DocComparator comparator = new DocComparatorAnonymousInnerClassHelper(this, reverseMul, comparators); return(Sort(reader.MaxDoc, comparator)); }
public override FieldComparator SetNextReader(AtomicReaderContext context) { DocIdSet innerDocuments = _childFilter.GetDocIdSet(context, null); if (IsEmpty(innerDocuments)) { _childDocuments = null; } else if (innerDocuments is FixedBitSet) { _childDocuments = (FixedBitSet)innerDocuments; } else { DocIdSetIterator iterator = innerDocuments.GetIterator(); _childDocuments = iterator != null?ToFixedBitSet(iterator, context.AtomicReader.MaxDoc) : null; } DocIdSet rootDocuments = _parentFilter.GetDocIdSet(context, null); if (IsEmpty(rootDocuments)) { _parentDocuments = null; } else if (rootDocuments is FixedBitSet) { _parentDocuments = (FixedBitSet)rootDocuments; } else { DocIdSetIterator iterator = rootDocuments.GetIterator(); _parentDocuments = iterator != null?ToFixedBitSet(iterator, context.AtomicReader.MaxDoc) : null; } _wrappedComparator = _wrappedComparator.SetNextReader(context); return(this); }
public LuceneCustomDocComparator(FieldComparator luceneComparator) { this._luceneComparator = luceneComparator; }
public LuceneCustomDocComparatorSource(string fieldname, FieldComparator luceneComparator) { _fieldname = fieldname; _luceneComparator = luceneComparator; }
public override void Collect(int doc) { //System.out.println("FP.collect doc=" + doc); // If orderedGroups != null we already have collected N groups and // can short circuit by comparing this document to the bottom group, // without having to find what group this document belongs to. // Even if this document belongs to a group in the top N, we'll know that // we don't have to update that group. // Downside: if the number of unique groups is very low, this is // wasted effort as we will most likely be updating an existing group. if (orderedGroups != null) { for (int compIDX = 0; ; compIDX++) { int c = reversed[compIDX] * comparators[compIDX].CompareBottom(doc); if (c < 0) { // Definitely not competitive. So don't even bother to continue return; } else if (c > 0) { // Definitely competitive. break; } else if (compIDX == compIDXEnd) { // Here c=0. If we're at the last comparator, this doc is not // competitive, since docs are visited in doc Id order, which means // this doc cannot compete with any other document in the queue. return; } } } // TODO: should we add option to mean "ignore docs that // don't have the group field" (instead of stuffing them // under null group)? TGroupValue groupValue = GetDocGroupValue(doc); CollectedSearchGroup <TGroupValue> group; if (!groupMap.TryGetValue(groupValue, out group)) { // First time we are seeing this group, or, we've seen // it before but it fell out of the top N and is now // coming back if (groupMap.Count < topNGroups) { // Still in startup transient: we have not // seen enough unique groups to start pruning them; // just keep collecting them // Add a new CollectedSearchGroup: CollectedSearchGroup <TGroupValue> sg = new CollectedSearchGroup <TGroupValue>(); sg.GroupValue = CopyDocGroupValue(groupValue, default(TGroupValue)); sg.ComparatorSlot = groupMap.Count; sg.TopDoc = docBase + doc; foreach (FieldComparator fc in comparators) { fc.Copy(sg.ComparatorSlot, doc); } groupMap[sg.GroupValue] = sg; if (groupMap.Count == topNGroups) { // End of startup transient: we now have max // number of groups; from here on we will drop // bottom group when we insert new one: BuildSortedSet(); } return; } // We already tested that the document is competitive, so replace // the bottom group with this new group. //CollectedSearchGroup<TGroupValue> bottomGroup = orderedGroups.PollLast(); CollectedSearchGroup <TGroupValue> bottomGroup; lock (orderedGroups) { bottomGroup = orderedGroups.Last(); orderedGroups.Remove(bottomGroup); } Debug.Assert(orderedGroups.Count == topNGroups - 1); groupMap.Remove(bottomGroup.GroupValue); // reuse the removed CollectedSearchGroup bottomGroup.GroupValue = CopyDocGroupValue(groupValue, bottomGroup.GroupValue); bottomGroup.TopDoc = docBase + doc; foreach (FieldComparator fc in comparators) { fc.Copy(bottomGroup.ComparatorSlot, doc); } groupMap[bottomGroup.GroupValue] = bottomGroup; orderedGroups.Add(bottomGroup); Debug.Assert(orderedGroups.Count == topNGroups); int lastComparatorSlot = orderedGroups.Last().ComparatorSlot; foreach (FieldComparator fc in comparators) { fc.Bottom = lastComparatorSlot; } return; } // Update existing group: for (int compIDX = 0; ; compIDX++) { FieldComparator fc = comparators[compIDX]; fc.Copy(spareSlot, doc); int c = reversed[compIDX] * fc.Compare(group.ComparatorSlot, spareSlot); if (c < 0) { // Definitely not competitive. return; } else if (c > 0) { // Definitely competitive; set remaining comparators: for (int compIDX2 = compIDX + 1; compIDX2 < comparators.Length; compIDX2++) { comparators[compIDX2].Copy(spareSlot, doc); } break; } else if (compIDX == compIDXEnd) { // Here c=0. If we're at the last comparator, this doc is not // competitive, since docs are visited in doc Id order, which means // this doc cannot compete with any other document in the queue. return; } } // Remove before updating the group since lookup is done via comparators // TODO: optimize this CollectedSearchGroup <TGroupValue> prevLast; if (orderedGroups != null) { lock (orderedGroups) { prevLast = orderedGroups.Last(); orderedGroups.Remove(group); } Debug.Assert(orderedGroups.Count == topNGroups - 1); } else { prevLast = null; } group.TopDoc = docBase + doc; // Swap slots int tmp = spareSlot; spareSlot = group.ComparatorSlot; group.ComparatorSlot = tmp; // Re-add the changed group if (orderedGroups != null) { orderedGroups.Add(group); Debug.Assert(orderedGroups.Count == topNGroups); var newLast = orderedGroups.Last(); // If we changed the value of the last group, or changed which group was last, then update bottom: if (group == newLast || prevLast != newLast) { foreach (FieldComparator fc in comparators) { fc.Bottom = newLast.ComparatorSlot; } } } }
public TestFieldComparator(FieldComparator comparator, List <string> diagnostics) { _comparator = comparator ?? throw new ArgumentNullException(nameof(comparator)); _diagnostics = diagnostics; }
/// <summary> /// Create ToParentBlockJoinFieldComparator.Highest /// </summary> /// <param name="wrappedComparator">The <see cref="FieldComparator"/> on the child / nested level. </param> /// <param name="parentFilter">Filter (must produce FixedBitSet per-segment) that identifies the parent documents. </param> /// <param name="childFilter">Filter that defines which child / nested documents participates in sorting. </param> /// <param name="spareSlot">The extra slot inside the wrapped comparator that is used to compare which nested document /// inside the parent document scope is most competitive. </param> public Highest(FieldComparator wrappedComparator, Filter parentFilter, Filter childFilter, int spareSlot) : base(wrappedComparator, parentFilter, childFilter, spareSlot) { }