Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address MinAndMax generics warnings #52642

Merged
merged 6 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private static boolean shouldSortShards(MinAndMax<?>[] minAndMaxes) {
private static Comparator<Integer> shardComparator(GroupShardsIterator<SearchShardIterator> shardsIts,
MinAndMax<?>[] minAndMaxes,
SortOrder order) {
final Comparator<Integer> comparator = Comparator.comparing(index -> minAndMaxes[index], MinAndMax.getComparator(order));
final Comparator<Integer> comparator = Comparator.comparing(index -> minAndMaxes[index], MinAndMax.getComparator(order));
return comparator.thenComparing(index -> shardsIts.get(index).shardId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,46 +429,6 @@ public static FieldSortBuilder getPrimaryFieldSortOrNull(SearchSourceBuilder sou
return source.sorts().get(0) instanceof FieldSortBuilder ? (FieldSortBuilder) source.sorts().get(0) : null;
}

/**
* Return a {@link Function} that converts a serialized point into a {@link Number} according to the provided
* {@link SortField}. This is needed for {@link SortField} that converts values from one type to another using
* {@link FieldSortBuilder#setNumericType(String)} )} (e.g.: long to double).
*/
private static Function<byte[], Comparable> numericPointConverter(SortField sortField, NumberFieldType numberFieldType) {
switch (IndexSortConfig.getSortFieldType(sortField)) {
case LONG:
return v -> numberFieldType.parsePoint(v).longValue();

case INT:
return v -> numberFieldType.parsePoint(v).intValue();

case DOUBLE:
return v -> numberFieldType.parsePoint(v).doubleValue();

case FLOAT:
return v -> numberFieldType.parsePoint(v).floatValue();

default:
return v -> null;
}
}

/**
* Return a {@link Function} that converts a serialized date point into a {@link Long} according to the provided
* {@link NumericType}.
*/
private static Function<byte[], Comparable> datePointConverter(DateFieldType dateFieldType, String numericTypeStr) {
if (numericTypeStr != null) {
NumericType numericType = resolveNumericType(numericTypeStr);
if (dateFieldType.resolution() == MILLISECONDS && numericType == NumericType.DATE_NANOSECONDS) {
return v -> DateUtils.toNanoSeconds(LongPoint.decodeDimension(v, 0));
} else if (dateFieldType.resolution() == NANOSECONDS && numericType == NumericType.DATE) {
return v -> DateUtils.toMilliSeconds(LongPoint.decodeDimension(v, 0));
}
}
return v -> LongPoint.decodeDimension(v, 0);
}

/**
* Return the {@link MinAndMax} indexed value from the provided {@link FieldSortBuilder} or <code>null</code> if unknown.
* The value can be extracted on non-nested indexed mapped fields of type keyword, numeric or date, other fields
Expand All @@ -485,41 +445,73 @@ public static MinAndMax<?> getMinMaxOrNull(QueryShardContext context, FieldSortB
if (reader == null || (fieldType == null || fieldType.indexOptions() == IndexOptions.NONE)) {
return null;
}
String fieldName = fieldType.name();
switch (IndexSortConfig.getSortFieldType(sortField)) {
case LONG:
case INT:
case DOUBLE:
case FLOAT:
final Function<byte[], Comparable> converter;
if (fieldType instanceof NumberFieldType) {
converter = numericPointConverter(sortField, (NumberFieldType) fieldType);
} else if (fieldType instanceof DateFieldType) {
converter = datePointConverter((DateFieldType) fieldType, sortBuilder.getNumericType());
} else {
return null;
}
if (PointValues.size(reader, fieldName) == 0) {
return null;
}
final Comparable min = converter.apply(PointValues.getMinPackedValue(reader, fieldName));
final Comparable max = converter.apply(PointValues.getMaxPackedValue(reader, fieldName));
return MinAndMax.newMinMax(min, max);

return extractNumericMinAndMax(reader, sortField, fieldType, sortBuilder);
case STRING:
case STRING_VAL:
if (fieldType instanceof KeywordFieldMapper.KeywordFieldType) {
Terms terms = MultiTerms.getTerms(reader, fieldName);
Terms terms = MultiTerms.getTerms(reader, fieldType.name());
if (terms == null) {
return null;
}
return terms.getMin() != null ? MinAndMax.newMinMax(terms.getMin(), terms.getMax()) : null;
return terms.getMin() != null ? new MinAndMax<>(terms.getMin(), terms.getMax()) : null;
}
break;
}
return null;
}

private static MinAndMax<?> extractNumericMinAndMax(IndexReader reader,
SortField sortField,
MappedFieldType fieldType,
FieldSortBuilder sortBuilder) throws IOException {
String fieldName = fieldType.name();
if (PointValues.size(reader, fieldName) == 0) {
return null;
}
if (fieldType instanceof NumberFieldType) {
NumberFieldType numberFieldType = (NumberFieldType) fieldType;
Number minPoint = numberFieldType.parsePoint(PointValues.getMinPackedValue(reader, fieldName));
Number maxPoint = numberFieldType.parsePoint(PointValues.getMaxPackedValue(reader, fieldName));
switch (IndexSortConfig.getSortFieldType(sortField)) {
case LONG:
return new MinAndMax<>(minPoint.longValue(), maxPoint.longValue());
case INT:
return new MinAndMax<>(minPoint.intValue(), maxPoint.intValue());
case DOUBLE:
return new MinAndMax<>(minPoint.doubleValue(), maxPoint.doubleValue());
case FLOAT:
return new MinAndMax<>(minPoint.floatValue(), maxPoint.floatValue());
default:
return null;
}
} else if (fieldType instanceof DateFieldType) {
DateFieldType dateFieldType = (DateFieldType) fieldType;
Function<byte[], Long> dateConverter = createDateConverter(sortBuilder, dateFieldType);
Long min = dateConverter.apply(PointValues.getMinPackedValue(reader, fieldName));
Long max = dateConverter.apply(PointValues.getMaxPackedValue(reader, fieldName));
return new MinAndMax<>(min, max);
}
return null;
}

private static Function<byte[], Long> createDateConverter(FieldSortBuilder sortBuilder, DateFieldType dateFieldType) {
String numericTypeStr = sortBuilder.getNumericType();
if (numericTypeStr != null) {
NumericType numericType = resolveNumericType(numericTypeStr);
if (dateFieldType.resolution() == MILLISECONDS && numericType == NumericType.DATE_NANOSECONDS) {
return v -> DateUtils.toNanoSeconds(LongPoint.decodeDimension(v, 0));
} else if (dateFieldType.resolution() == NANOSECONDS && numericType == NumericType.DATE) {
return v -> DateUtils.toMilliSeconds(LongPoint.decodeDimension(v, 0));
}
}
return v -> LongPoint.decodeDimension(v, 0);
}

/**
* Throws an exception if max children is not located at top level nested sort.
*/
Expand Down Expand Up @@ -601,12 +593,12 @@ public static FieldSortBuilder fromXContent(XContentParser parser, String fieldN
private static final ObjectParser<FieldSortBuilder, Void> PARSER = new ObjectParser<>(NAME);

static {
PARSER.declareField(FieldSortBuilder::missing, p -> p.objectText(), MISSING, ValueType.VALUE);
PARSER.declareField(FieldSortBuilder::missing, XContentParser::objectText, MISSING, ValueType.VALUE);
PARSER.declareString(FieldSortBuilder::unmappedType , UNMAPPED_TYPE);
PARSER.declareString((b, v) -> b.order(SortOrder.fromString(v)) , ORDER_FIELD);
PARSER.declareString((b, v) -> b.sortMode(SortMode.fromString(v)), SORT_MODE);
PARSER.declareObject(FieldSortBuilder::setNestedSort, (p, c) -> NestedSortBuilder.fromXContent(p), NESTED_FIELD);
PARSER.declareString((b, v) -> b.setNumericType(v), NUMERIC_TYPE);
PARSER.declareString(FieldSortBuilder::setNumericType, NUMERIC_TYPE);
}

@Override
Expand Down
21 changes: 9 additions & 12 deletions server/src/main/java/org/elasticsearch/search/sort/MinAndMax.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@
import java.util.Objects;

/**
* A class that encapsulates a minimum and a maximum {@link Comparable}.
* A class that encapsulates a minimum and a maximum, that are of the same type and {@link Comparable}.
*/
public class MinAndMax<T extends Comparable<? super T>> implements Writeable {
private final T minValue;
private final T maxValue;

private MinAndMax(T minValue, T maxValue) {
public MinAndMax(T minValue, T maxValue) {
this.minValue = Objects.requireNonNull(minValue);
this.maxValue = Objects.requireNonNull(maxValue);
}

@SuppressWarnings("unchecked")
public MinAndMax(StreamInput in) throws IOException {
this.minValue = (T) Lucene.readSortValue(in);
this.maxValue = (T) Lucene.readSortValue(in);
this.minValue = (T)Lucene.readSortValue(in);
this.maxValue = (T)Lucene.readSortValue(in);
}

@Override
Expand All @@ -54,27 +55,23 @@ public void writeTo(StreamOutput out) throws IOException {
/**
* Return the minimum value.
*/
public T getMin() {
T getMin() {
return minValue;
}

/**
* Return the maximum value.
*/
public T getMax() {
T getMax() {
return maxValue;
}

public static <T extends Comparable<? super T>> MinAndMax<T> newMinMax(T min, T max) {
return new MinAndMax<>(min, max);
}

/**
* Return a {@link Comparator} for {@link MinAndMax} values according to the provided {@link SortOrder}.
*/
public static Comparator<MinAndMax<?>> getComparator(SortOrder order) {
Comparator<MinAndMax> cmp = order == SortOrder.ASC ?
Comparator.comparing(v -> (Comparable) v.getMin()) : Comparator.comparing(v -> (Comparable) v.getMax());
Comparator<MinAndMax<?>> cmp = order == SortOrder.ASC ?
Comparator.comparing(MinAndMax::getMin) : Comparator.comparing(MinAndMax::getMax);
if (order == SortOrder.DESC) {
cmp = cmp.reversed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ public void sendCanMatch(Transport.Connection connection, ShardSearchRequest req
ActionListener<SearchService.CanMatchResponse> listener) {
Long min = rarely() ? null : randomLong();
Long max = min == null ? null : randomLongBetween(min, Long.MAX_VALUE);
MinAndMax<?> minMax = min == null ? null : MinAndMax.newMinMax(min, max);
MinAndMax<?> minMax = min == null ? null : new MinAndMax<>(min, max);
boolean canMatch = frequently();
synchronized (shardIds) {
shardIds.add(request.shardId());
Expand Down