mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-03 09:29:11 +00:00
Fix max/min aggs for unsigned_long (#63904)
Max and min aggs were producing wrong results for unsigned_long field if field was indexed. If field is indexed for max/min aggs instead of field data, we use values from indexed Points, values of which are derived using method pointReaderIfPossible. Before UnsignedLongFieldType#pointReaderIfPossible was incorrectly producing values, as it failed to shift them back to original values. This patch fixes method pointReaderIfPossible to produce correct original values. Relates to #60050
This commit is contained in:
parent
3369216087
commit
1287df4074
@ -49,6 +49,8 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static org.elasticsearch.xpack.unsignedlong.UnsignedLongLeafFieldData.convertUnsignedLongToDouble;
|
||||||
|
|
||||||
public class UnsignedLongFieldMapper extends ParametrizedFieldMapper {
|
public class UnsignedLongFieldMapper extends ParametrizedFieldMapper {
|
||||||
public static final String CONTENT_TYPE = "unsigned_long";
|
public static final String CONTENT_TYPE = "unsigned_long";
|
||||||
|
|
||||||
@ -272,7 +274,8 @@ public class UnsignedLongFieldMapper extends ParametrizedFieldMapper {
|
|||||||
@Override
|
@Override
|
||||||
public Function<byte[], Number> pointReaderIfPossible() {
|
public Function<byte[], Number> pointReaderIfPossible() {
|
||||||
if (isSearchable()) {
|
if (isSearchable()) {
|
||||||
return (value) -> LongPoint.decodeDimension(value, 0);
|
// convert from the shifted value back to the original value
|
||||||
|
return (value) -> convertUnsignedLongToDouble(LongPoint.decodeDimension(value, 0));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -520,7 +523,7 @@ public class UnsignedLongFieldMapper extends ParametrizedFieldMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an unsigned long to the singed long by subtract 2^63 from it
|
* Convert an unsigned long to the signed long by subtract 2^63 from it
|
||||||
* @param value – unsigned long value in the range [0; 2^64-1], values greater than 2^63-1 are negative
|
* @param value – unsigned long value in the range [0; 2^64-1], values greater than 2^63-1 are negative
|
||||||
* @return signed long value in the range [-2^63; 2^63-1]
|
* @return signed long value in the range [-2^63; 2^63-1]
|
||||||
*/
|
*/
|
||||||
|
@ -112,7 +112,7 @@ public class UnsignedLongLeafFieldData implements LeafNumericFieldData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double convertUnsignedLongToDouble(long value) {
|
static double convertUnsignedLongToDouble(long value) {
|
||||||
if (value < 0L) {
|
if (value < 0L) {
|
||||||
return sortableSignedLongToUnsigned(value); // add 2 ^ 63
|
return sortableSignedLongToUnsigned(value); // add 2 ^ 63
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,7 +20,9 @@ import org.elasticsearch.search.SearchHit;
|
|||||||
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
||||||
import org.elasticsearch.search.aggregations.bucket.range.Range;
|
import org.elasticsearch.search.aggregations.bucket.range.Range;
|
||||||
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
||||||
|
import org.elasticsearch.search.aggregations.metrics.Min;
|
||||||
import org.elasticsearch.search.aggregations.metrics.Sum;
|
import org.elasticsearch.search.aggregations.metrics.Sum;
|
||||||
|
import org.elasticsearch.search.aggregations.metrics.Max;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.elasticsearch.test.ESIntegTestCase;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
|
|
||||||
@ -35,6 +37,8 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
|||||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.histogram;
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.histogram;
|
||||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.range;
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.range;
|
||||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;
|
||||||
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.max;
|
||||||
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.min;
|
||||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
|
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
||||||
@ -279,6 +283,20 @@ public class UnsignedLongTests extends ESIntegTestCase {
|
|||||||
double expectedSum = Arrays.stream(values).mapToDouble(Number::doubleValue).sum();
|
double expectedSum = Arrays.stream(values).mapToDouble(Number::doubleValue).sum();
|
||||||
assertEquals(expectedSum, sum.getValue(), 0.001);
|
assertEquals(expectedSum, sum.getValue(), 0.001);
|
||||||
}
|
}
|
||||||
|
// max agg
|
||||||
|
{
|
||||||
|
SearchResponse response = client().prepareSearch("idx").setSize(0).addAggregation(max("ul_max").field("ul_field")).get();
|
||||||
|
assertSearchResponse(response);
|
||||||
|
Max max = response.getAggregations().get("ul_max");
|
||||||
|
assertEquals(1.8446744073709551615E19, max.getValue(), 0.001);
|
||||||
|
}
|
||||||
|
// min agg
|
||||||
|
{
|
||||||
|
SearchResponse response = client().prepareSearch("idx").setSize(0).addAggregation(min("ul_min").field("ul_field")).get();
|
||||||
|
assertSearchResponse(response);
|
||||||
|
Min min = response.getAggregations().get("ul_min");
|
||||||
|
assertEquals(0, min.getValue(), 0.001);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSortDifferentFormatsShouldFail() {
|
public void testSortDifferentFormatsShouldFail() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user