下面列出了怎么用org.apache.lucene.search.FieldComparator的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
return new FieldComparator<Object>() {
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return LEAF_FIELD_COMPARATOR;
}
@Override
public int compare(int slot1, int slot2) {
return 0;
}
@Override
public void setTopValue(Object value) {
}
@Override
public Object value(int slot) {
return missingValue;
}
};
}
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
assert indexFieldData == null || fieldname.equals(indexFieldData.getFieldNames().indexName());
final Long dMissingValue = (Long) missingObject(missingValue, reversed);
// NOTE: it's important to pass null as a missing value in the constructor so that
// the comparator doesn't check docsWithField since we replace missing values in select()
return new FieldComparator.LongComparator(numHits, null, null) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
final SortedNumericDocValues values = indexFieldData.load(context).getLongValues();
final NumericDocValues selectedValues;
if (nested == null) {
selectedValues = sortMode.select(values, dMissingValue);
} else {
final BitSet rootDocs = nested.rootDocs(context);
final DocIdSetIterator innerDocs = nested.innerDocs(context);
selectedValues = sortMode.select(values, dMissingValue, rootDocs, innerDocs, context.reader().maxDoc());
}
return selectedValues;
}
};
}
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
assert indexFieldData == null || fieldname.equals(indexFieldData.getFieldNames().indexName());
final float dMissingValue = (Float) missingObject(missingValue, reversed);
// NOTE: it's important to pass null as a missing value in the constructor so that
// the comparator doesn't check docsWithField since we replace missing values in select()
return new FieldComparator.FloatComparator(numHits, null, null) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
final SortedNumericDoubleValues values = indexFieldData.load(context).getDoubleValues();
final NumericDoubleValues selectedValues;
if (nested == null) {
selectedValues = sortMode.select(values, dMissingValue);
} else {
final BitSet rootDocs = nested.rootDocs(context);
final DocIdSetIterator innerDocs = nested.innerDocs(context);
selectedValues = sortMode.select(values, dMissingValue, rootDocs, innerDocs, context.reader().maxDoc());
}
return selectedValues.getRawFloatValues();
}
};
}
@Override
public FieldComparator<?> getComparator(int numHits, int sortPos) {
switch (getType()) {
case STRING:
return getStringComparator(numHits);
case DOUBLE:
return getDoubleComparator(numHits);
case FLOAT:
return getFloatComparator(numHits);
case LONG:
return getLongComparator(numHits);
case INT:
return getIntComparator(numHits);
default:
throw new UnsupportedOperationException("Sort type " + getType() + " is not supported");
}
}
private FieldComparator<?> getStringComparator(int numHits) {
return new FieldComparator.TermOrdValComparator(numHits, getField(), missingValue == STRING_LAST) {
@Override
protected SortedDocValues getSortedDocValues(LeafReaderContext context, String field) throws IOException {
SortedSetDocValues sortedSet = DocValues.getSortedSet(context.reader(), field);
final BlockJoinSelector.Type type = order
? BlockJoinSelector.Type.MAX
: BlockJoinSelector.Type.MIN;
final BitSet parents = parentFilter.getBitSet(context);
final BitSet children = childFilter.getBitSet(context);
if (children == null) {
return DocValues.emptySorted();
}
return BlockJoinSelector.wrap(sortedSet, type, parents, toIter(children));
}
};
}
private FieldComparator<?> getIntComparator(int numHits) {
return new FieldComparator.IntComparator(numHits, getField(), (Integer) missingValue) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
SortedNumericDocValues sortedNumeric = DocValues.getSortedNumeric(context.reader(), field);
final BlockJoinSelector.Type type = order
? BlockJoinSelector.Type.MAX
: BlockJoinSelector.Type.MIN;
final BitSet parents = parentFilter.getBitSet(context);
final BitSet children = childFilter.getBitSet(context);
if (children == null) {
return DocValues.emptyNumeric();
}
return BlockJoinSelector.wrap(sortedNumeric, type, parents, toIter(children));
}
};
}
private FieldComparator<?> getLongComparator(int numHits) {
return new FieldComparator.LongComparator(numHits, getField(), (Long) missingValue) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
SortedNumericDocValues sortedNumeric = DocValues.getSortedNumeric(context.reader(), field);
final BlockJoinSelector.Type type = order
? BlockJoinSelector.Type.MAX
: BlockJoinSelector.Type.MIN;
final BitSet parents = parentFilter.getBitSet(context);
final BitSet children = childFilter.getBitSet(context);
if (children == null) {
return DocValues.emptyNumeric();
}
return BlockJoinSelector.wrap(sortedNumeric, type, parents, toIter(children));
}
};
}
private FieldComparator<?> getFloatComparator(int numHits) {
return new FieldComparator.FloatComparator(numHits, getField(), (Float) missingValue) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
SortedNumericDocValues sortedNumeric = DocValues.getSortedNumeric(context.reader(), field);
final BlockJoinSelector.Type type = order
? BlockJoinSelector.Type.MAX
: BlockJoinSelector.Type.MIN;
final BitSet parents = parentFilter.getBitSet(context);
final BitSet children = childFilter.getBitSet(context);
if (children == null) {
return DocValues.emptyNumeric();
}
return new FilterNumericDocValues(BlockJoinSelector.wrap(sortedNumeric, type, parents, toIter(children))) {
@Override
public long longValue() throws IOException {
// undo the numericutils sortability
return NumericUtils.sortableFloatBits((int) super.longValue());
}
};
}
};
}
private FieldComparator<?> getDoubleComparator(int numHits) {
return new FieldComparator.DoubleComparator(numHits, getField(), (Double) missingValue) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
SortedNumericDocValues sortedNumeric = DocValues.getSortedNumeric(context.reader(), field);
final BlockJoinSelector.Type type = order
? BlockJoinSelector.Type.MAX
: BlockJoinSelector.Type.MIN;
final BitSet parents = parentFilter.getBitSet(context);
final BitSet children = childFilter.getBitSet(context);
if (children == null) {
return DocValues.emptyNumeric();
}
return new FilterNumericDocValues(BlockJoinSelector.wrap(sortedNumeric, type, parents, toIter(children))) {
@Override
public long longValue() throws IOException {
// undo the numericutils sortability
return NumericUtils.sortableDoubleBits(super.longValue());
}
};
}
};
}
@SuppressWarnings({"rawtypes"})
public SortFieldsCompare(SortField[] sorts, int initNumGroups) {
this.sorts = sorts;
numClauses = sorts.length;
fieldComparators = new FieldComparator[numClauses];
leafFieldComparators = new LeafFieldComparator[numClauses];
reverseMul = new int[numClauses];
for (int clause = 0; clause < numClauses; clause++) {
SortField sf = sorts[clause];
// we only need one slot for every comparator
fieldComparators[clause] = sf.getComparator(1, clause);
reverseMul[clause] = sf.getReverse() ? -1 : 1;
}
groupHeadValues = new Object[initNumGroups][];
nullGroupValues = new Object[numClauses];
}
@Override
public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
return new DoubleValues() {
@SuppressWarnings("unchecked")
final FieldComparator<Double> comparator =
(FieldComparator<Double>) getSortField(false).getComparator(1, 1);
final LeafFieldComparator leafComparator = comparator.getLeafComparator(ctx);
final double mult = multiplier; // so it's a local field
double value = Double.POSITIVE_INFINITY;
@Override
public double doubleValue() throws IOException {
return value;
}
@Override
public boolean advanceExact(int doc) throws IOException {
leafComparator.copy(0, doc);
value = comparator.value(0) * mult;
return true;
}
};
}
@SuppressWarnings("rawtypes")
Comparator<ShardDoc> comparatorFieldComparator(SortField sortField) {
final FieldComparator fieldComparator;
try {
fieldComparator = sortField.getComparator(0, 0);
} catch (IOException e) {
throw new RuntimeException("Unable to get FieldComparator for sortField " + sortField);
}
return new ShardComparator(sortField) {
// Since the PriorityQueue keeps the biggest elements by default,
// we need to reverse the field compare ordering so that the
// smallest elements are kept instead of the largest... hence
// the negative sign.
@Override
@SuppressWarnings("unchecked")
public int compare(final ShardDoc o1, final ShardDoc o2) {
// noinspection unchecked
return -fieldComparator.compareValues(sortVal(o1), sortVal(o2));
}
};
}
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) {
return new FieldComparator<>() {
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) {
return LEAF_FIELD_COMPARATOR;
}
@Override
public int compare(int slot1, int slot2) {
return 0;
}
@Override
public void setTopValue(Object value) {
}
@Override
public Object value(int slot) {
return nullSentinel;
}
};
}
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
assert indexFieldData == null || fieldname.equals(indexFieldData.getFieldNames().indexName());
final double dMissingValue = (Double) missingObject(missingValue, reversed);
// NOTE: it's important to pass null as a missing value in the constructor so that
// the comparator doesn't check docsWithField since we replace missing values in select()
return new FieldComparator.DoubleComparator(numHits, null, null) {
@Override
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
final SortedNumericDoubleValues values = getValues(context);
final NumericDoubleValues selectedValues;
if (nested == null) {
selectedValues = sortMode.select(values, dMissingValue);
} else {
final BitSet rootDocs = nested.rootDocs(context);
final DocIdSetIterator innerDocs = nested.innerDocs(context);
selectedValues = sortMode.select(values, dMissingValue, rootDocs, innerDocs, context.reader().maxDoc());
}
return selectedValues.getRawDoubleValues();
}
@Override
public void setScorer(Scorer scorer) {
DoubleValuesComparatorSource.this.setScorer(scorer);
}
};
}
protected SortingGroupHead(Sort sort, T groupValue, int doc, LeafReaderContext context, Scorable scorer) throws IOException {
super(groupValue, doc, context.docBase);
final SortField[] sortFields = sort.getSort();
comparators = new FieldComparator[sortFields.length];
leafComparators = new LeafFieldComparator[sortFields.length];
for (int i = 0; i < sortFields.length; i++) {
comparators[i] = sortFields[i].getComparator(1, i);
leafComparators[i] = comparators[i].getLeafComparator(context);
leafComparators[i].setScorer(scorer);
leafComparators[i].copy(0, doc);
leafComparators[i].setBottom(0);
}
}
/**
* Create the single pass collector.
*
* @param groupSort The {@link Sort} used to sort the
* groups. The top sorted document within each group
* according to groupSort, determines how that group
* sorts against other groups. This must be non-null,
* ie, if you want to groupSort by relevance use
* Sort.RELEVANCE.
* @param topNGroups How many top groups to keep.
* @param needsScores true if the collected documents
* require scores, either because relevance is included
* in the withinGroupSort or because you plan to pass true
* for either getSscores or getMaxScores to {@link
* #getTopGroups}
* @param lastDocPerGroup a {@link Weight} that marks the
* last document in each group.
*/
public BlockGroupingCollector(Sort groupSort, int topNGroups, boolean needsScores, Weight lastDocPerGroup) {
if (topNGroups < 1) {
throw new IllegalArgumentException("topNGroups must be >= 1 (got " + topNGroups + ")");
}
groupQueue = new GroupQueue(topNGroups);
pendingSubDocs = new int[10];
if (needsScores) {
pendingSubScores = new float[10];
}
this.needsScores = needsScores;
this.lastDocPerGroup = lastDocPerGroup;
this.groupSort = groupSort;
this.topNGroups = topNGroups;
final SortField[] sortFields = groupSort.getSort();
comparators = new FieldComparator<?>[sortFields.length];
leafComparators = new LeafFieldComparator[sortFields.length];
compIDXEnd = comparators.length - 1;
reversed = new int[sortFields.length];
for (int i = 0; i < sortFields.length; i++) {
final SortField sortField = sortFields[i];
comparators[i] = sortField.getComparator(topNGroups, i);
reversed[i] = sortField.getReverse() ? -1 : 1;
}
}
/**
* Create the first pass collector.
*
* @param groupSelector a GroupSelector used to defined groups
* @param groupSort The {@link Sort} used to sort the
* groups. The top sorted document within each group
* according to groupSort, determines how that group
* sorts against other groups. This must be non-null,
* ie, if you want to groupSort by relevance use
* Sort.RELEVANCE.
* @param topNGroups How many top groups to keep.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public FirstPassGroupingCollector(GroupSelector<T> groupSelector, Sort groupSort, int topNGroups) {
this.groupSelector = groupSelector;
if (topNGroups < 1) {
throw new IllegalArgumentException("topNGroups must be >= 1 (got " + topNGroups + ")");
}
// TODO: allow null groupSort to mean "by relevance",
// and specialize it?
this.topNGroups = topNGroups;
this.needsScores = groupSort.needsScores();
final SortField[] sortFields = groupSort.getSort();
comparators = new FieldComparator[sortFields.length];
leafComparators = new LeafFieldComparator[sortFields.length];
compIDXEnd = comparators.length - 1;
reversed = new int[sortFields.length];
for (int i = 0; i < sortFields.length; i++) {
final SortField sortField = sortFields[i];
// use topNGroups + 1 so we have a spare slot to use for comparing (tracked by this.spareSlot):
comparators[i] = sortField.getComparator(topNGroups + 1, i);
reversed[i] = sortField.getReverse() ? -1 : 1;
}
spareSlot = topNGroups;
groupMap = new HashMap<>(topNGroups);
}
@SuppressWarnings({"unchecked", "rawtypes"})
public GroupComparator(Sort groupSort) {
final SortField[] sortFields = groupSort.getSort();
comparators = new FieldComparator[sortFields.length];
reversed = new int[sortFields.length];
for (int compIDX = 0; compIDX < sortFields.length; compIDX++) {
final SortField sortField = sortFields[compIDX];
comparators[compIDX] = sortField.getComparator(1, compIDX);
reversed[compIDX] = sortField.getReverse() ? -1 : 1;
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private boolean testAndSetGroupValues(Object[] values, int contextDoc) throws IOException {
Object[] stash = new Object[numClauses];
int lastCompare = 0;
int testClause = 0;
for (/* testClause */; testClause < numClauses; testClause++) {
leafFieldComparators[testClause].copy(0, contextDoc);
FieldComparator fcomp = fieldComparators[testClause];
stash[testClause] = cloneIfBytesRef(fcomp.value(0));
lastCompare = reverseMul[testClause] * fcomp.compareValues(stash[testClause], values[testClause]);
if (0 != lastCompare) {
// no need to keep checking additional clauses
break;
}
}
if (0 <= lastCompare) {
// we're either not competitive, or we're completely tied with another doc that's already group head
// that's already been selected
return false;
} // else...
// this doc is our new group head, we've already read some of the values into our stash
testClause++;
System.arraycopy(stash, 0, values, 0, testClause);
// read the remaining values we didn't need to test
for (int copyClause = testClause; copyClause < numClauses; copyClause++) {
leafFieldComparators[copyClause].copy(0, contextDoc);
values[copyClause] = cloneIfBytesRef(fieldComparators[copyClause].value(0));
}
return true;
}
@Override
public SortField getSortField(boolean reverse) {
final Type type = childField.getSortField(reverse).getType();
return new ToParentBlockJoinSortField(childField.getName(),
type, reverse,
parentFilter, childFilter) {
@SuppressWarnings("unchecked")
@Override
public FieldComparator<?> getComparator(int numHits, int sortPos) {
final FieldComparator<?> comparator = super.getComparator(numHits, sortPos);
return type ==Type.STRING ? new BytesToStringComparator((FieldComparator<BytesRef>) comparator)
: comparator;
}
};
}
Comparator<ShardDoc> comparatorFieldComparator(SortField sortField) {
@SuppressWarnings({"rawtypes"})
final FieldComparator fieldComparator = sortField.getComparator(0, 0);
return new ShardComparator(sortField) {
// Since the PriorityQueue keeps the biggest elements by default,
// we need to reverse the field compare ordering so that the
// smallest elements are kept instead of the largest... hence
// the negative sign.
@Override
@SuppressWarnings({"unchecked"})
public int compare(final ShardDoc o1, final ShardDoc o2) {
return -fieldComparator.compareValues(sortVal(o1), sortVal(o2));
}
};
}
public BinarySortField(final String field, final boolean reverse) {
super(field, new FieldComparatorSource() {
@Override
public FieldComparator.TermOrdValComparator newComparator
(final String fieldname, final int numHits, final int sortPos, final boolean reversed) {
return new FieldComparator.TermOrdValComparator(numHits, fieldname);
}}, reverse);
}
/**
* Returns a Lucene {@link SortField} array for sorting documents/rows according to the column family name.
*
* @return A Lucene {@link SortField} array for sorting documents/rows according to the column family name.
*/
public SortField[] sortFields() {
return new SortField[]{new SortField(FIELD_NAME, new FieldComparatorSource() {
@Override
public FieldComparator<?> newComparator(String field,
int hits,
int sort,
boolean reversed) throws IOException {
return new ClusteringKeySorter(ClusteringKeyMapper.this, hits, field);
}
})};
}
private SortField customSortField(String name,
final Symbol symbol,
final SortSymbolContext context) {
InputFactory.Context<? extends LuceneCollectorExpression<?>> inputContext = docInputFactory.getCtx(context.txnCtx);
final Input<?> input = inputContext.add(symbol);
final List<? extends LuceneCollectorExpression<?>> expressions = inputContext.expressions();
final CollectorContext collectorContext = context.context;
final boolean nullFirst = context.nullFirst;
return new SortField(name, new FieldComparatorSource() {
@Override
public FieldComparator<?> newComparator(String fieldName, int numHits, int sortPos, boolean reversed) {
for (int i = 0; i < expressions.size(); i++) {
expressions.get(i).startCollect(collectorContext);
}
@SuppressWarnings("unchecked")
DataType<Object> dataType = (DataType<Object>) symbol.valueType();
Object nullSentinel = NullSentinelValues.nullSentinel(
dataType,
NullValueOrder.fromFlag(nullFirst),
reversed);
return new InputFieldComparator(
numHits,
expressions,
input,
// for non `null` sentinel values, the nullSentinel already implies reverse+nullsFirst logic
// for `null` sentinels we need to have a comparator that can deal with that
nullSentinel == null
? nullFirst ^ reversed ? Comparator.nullsFirst(dataType) : Comparator.nullsLast(dataType)
: dataType,
nullSentinel
);
}
}, context.reverseFlag);
}
@Override
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
assert indexFieldData == null || fieldname.equals(indexFieldData.getFieldNames().indexName());
final boolean sortMissingLast = sortMissingLast(missingValue) ^ reversed;
final BytesRef missingBytes = (BytesRef) missingObject(missingValue, reversed);
if (indexFieldData instanceof IndexOrdinalsFieldData) {
return new FieldComparator.TermOrdValComparator(numHits, null, sortMissingLast) {
@Override
protected SortedDocValues getSortedDocValues(LeafReaderContext context, String field) throws IOException {
final RandomAccessOrds values = ((IndexOrdinalsFieldData) indexFieldData).load(context).getOrdinalsValues();
final SortedDocValues selectedValues;
if (nested == null) {
selectedValues = sortMode.select(values);
} else {
final BitSet rootDocs = nested.rootDocs(context);
final DocIdSetIterator innerDocs = nested.innerDocs(context);
selectedValues = sortMode.select(values, rootDocs, innerDocs);
}
if (sortMissingFirst(missingValue) || sortMissingLast(missingValue)) {
return selectedValues;
} else {
return new ReplaceMissing(selectedValues, missingBytes);
}
}
@Override
public void setScorer(Scorer scorer) {
BytesRefFieldComparatorSource.this.setScorer(scorer);
}
};
}
final BytesRef nullPlaceHolder = new BytesRef();
final BytesRef nonNullMissingBytes = missingBytes == null ? nullPlaceHolder : missingBytes;
return new FieldComparator.TermValComparator(numHits, null, sortMissingLast) {
@Override
protected BinaryDocValues getBinaryDocValues(LeafReaderContext context, String field) throws IOException {
final SortedBinaryDocValues values = getValues(context);
final BinaryDocValues selectedValues;
if (nested == null) {
selectedValues = sortMode.select(values, nonNullMissingBytes);
} else {
final BitSet rootDocs = nested.rootDocs(context);
final DocIdSetIterator innerDocs = nested.innerDocs(context);
selectedValues = sortMode.select(values, nonNullMissingBytes, rootDocs, innerDocs, context.reader().maxDoc());
}
return selectedValues;
}
@Override
protected Bits getDocsWithField(LeafReaderContext context, String field) throws IOException {
return new Bits.MatchAllBits(context.reader().maxDoc());
}
@Override
protected boolean isNull(int doc, BytesRef term) {
return term == nullPlaceHolder;
}
@Override
public void setScorer(Scorer scorer) {
BytesRefFieldComparatorSource.this.setScorer(scorer);
}
};
}
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new TextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
@Override
public FieldComparator<String> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
{
return new MLTextSortFieldComparator(numHits, fieldname, I18NUtil.getLocale());
}
@Override
public FieldComparator<?> getComparator(int numHits, int sortPos) {
return new Geo3DPointOutsideDistanceComparator(getField(), planetModel, distanceShape, numHits);
}
@Override
public FieldComparator<?> getComparator(int numHits, int sortPos) {
return new Geo3DPointDistanceComparator(getField(), planetModel, distanceShape, numHits);
}
@Override
public FieldComparator<Double> newComparator(String fieldname, int numHits,
int sortPos, boolean reversed) {
return new ValueSourceComparator(context, numHits);
}