71
71
import java .util .function .Consumer ;
72
72
import java .util .function .Function ;
73
73
74
+ import static java .lang .Math .min ;
74
75
import static org .elasticsearch .index .IndexMode .TIME_SERIES ;
75
76
import static org .elasticsearch .index .mapper .TimeSeriesParams .MetricType .POSITION ;
76
77
import static org .hamcrest .CoreMatchers .containsString ;
@@ -236,7 +237,7 @@ public void testCompleteForSizeAndNumDocuments(int size, int numPoints, boolean
236
237
sortValues [i ] = i ;
237
238
}
238
239
239
- int lineSize = Math . min (numPoints , size );
240
+ int lineSize = min (numPoints , size );
240
241
// re-sort line to be ascending
241
242
long [] linePoints = Arrays .copyOf (points , lineSize );
242
243
double [] lineSorts = Arrays .copyOf (sortValues , lineSize );
@@ -431,9 +432,11 @@ public void testGeoLine_Terms_TSDB_simplified() throws IOException {
431
432
private void assertGeoLine (SortOrder sortOrder , String group , InternalGeoLine geoLine , TestTSAssertionResults tsx , boolean complete ) {
432
433
long [] expectedAggPoints = tsx .expectedAggPoints .get (group );
433
434
double [] expectedAggSortValues = tsx .expectedAggSortValues .get (group );
434
- String prefix = "GeoLine[sort=" + sortOrder + ", use-timestamps=" + tsx .useTimestampField + "]" ;
435
+ String prefix = "GeoLine[sort=" + sortOrder + ", use-timestamps=" + tsx .useTimeSeriesAggregation + ", group='" + group + "' ]" ;
435
436
assertThat (prefix + " is complete" , geoLine .isComplete (), is (complete ));
436
- assertThat (prefix + " contents" , geoLine .line (), isGeoLine (tsx .useTimestampField , expectedAggPoints ));
437
+ // old geo_line has a bug whereby it can produce lines with truncation happening in the middle instead of the end
438
+ int checkCount = tsx .useTimeSeriesAggregation ? expectedAggPoints .length : min (expectedAggPoints .length / 2 , geoLine .line ().length );
439
+ assertThat (prefix + " contents" , geoLine .line (), isGeoLine (checkCount , expectedAggPoints ));
437
440
double [] sortValues = geoLine .sortVals ();
438
441
for (int i = 1 ; i < sortValues .length ; i ++) {
439
442
Matcher <Double > sortMatcher = switch (sortOrder ) {
@@ -442,37 +445,37 @@ private void assertGeoLine(SortOrder sortOrder, String group, InternalGeoLine ge
442
445
};
443
446
assertThat (prefix + " expect ordered '" + sortOrder + "' sort values" , sortValues [i ], sortMatcher );
444
447
}
445
- if (tsx . useTimestampField ) {
448
+ if (checkCount == expectedAggSortValues . length ) {
446
449
assertArrayEquals (prefix + " sort values" , expectedAggSortValues , sortValues , 0d );
447
450
} else {
448
- for (int i = 0 ; i < Math . min ( expectedAggSortValues . length , sortValues . length ) ; i ++) {
451
+ for (int i = 0 ; i < checkCount ; i ++) {
449
452
assertThat (prefix + " sort value " + i , expectedAggSortValues [i ], equalTo (sortValues [i ]));
450
453
}
451
454
}
452
455
}
453
456
454
- private Matcher <long []> isGeoLine (boolean matchLength , long [] line ) {
455
- return new TestGeoLineLongArrayMatcher (matchLength , line );
457
+ private Matcher <long []> isGeoLine (int checkCount , long [] line ) {
458
+ return new TestGeoLineLongArrayMatcher (checkCount , line );
456
459
}
457
460
458
461
private static class TestGeoLineLongArrayMatcher extends BaseMatcher <long []> {
459
- private final boolean matchLength ;
462
+ private final int checkCount ;
460
463
private final long [] expectedLine ;
461
464
private final ArrayList <String > failures = new ArrayList <>();
462
465
463
- private TestGeoLineLongArrayMatcher (boolean matchLength , long [] expectedLine ) {
464
- this .matchLength = matchLength ;
466
+ private TestGeoLineLongArrayMatcher (int checkCount , long [] expectedLine ) {
467
+ this .checkCount = checkCount ;
465
468
this .expectedLine = expectedLine ;
466
469
}
467
470
468
471
@ Override
469
472
public boolean matches (Object actualObj ) {
470
473
failures .clear ();
471
474
if (actualObj instanceof long [] actualLine ) {
472
- if (matchLength && actualLine .length != expectedLine .length ) {
475
+ if (checkCount == expectedLine . length && actualLine .length != expectedLine .length ) {
473
476
failures .add ("Expected length " + expectedLine .length + " but got " + actualLine .length );
474
477
}
475
- for (int i = 0 ; i < Math . min ( expectedLine . length , actualLine . length ) ; i ++) {
478
+ for (int i = 0 ; i < checkCount ; i ++) {
476
479
Point actual = asPoint (actualLine [i ]);
477
480
Point expected = asPoint (expectedLine [i ]);
478
481
if (actual .equals (expected ) == false ) {
@@ -646,22 +649,19 @@ private record TestConfig(
646
649
int missingTimestampFactor ,
647
650
int groupCount ,
648
651
SortOrder sortOrder ,
649
- boolean useTimestamp
652
+ boolean useTimeSeriesAggregation
650
653
) {
651
- private String sortField () {
652
- return useTimestamp ? "@timestamp" : "time_field" ;
653
- }
654
-
655
654
@ SuppressWarnings ("SameParameterValue" )
656
655
private GeoLineAggregationBuilder lineAggregationBuilder (String name , String valueField , String sortField ) {
657
656
MultiValuesSourceFieldConfig valueConfig = new MultiValuesSourceFieldConfig .Builder ().setFieldName (valueField ).build ();
658
657
GeoLineAggregationBuilder lineAggregationBuilder = new GeoLineAggregationBuilder (name ).point (valueConfig )
659
658
.sortOrder (sortOrder )
660
659
.size (maxPoints );
661
- if (useTimestamp ) {
660
+ if (useTimeSeriesAggregation ) {
662
661
// In time-series we do not set the sort field
663
662
return lineAggregationBuilder ;
664
663
} else {
664
+ // Without a time-series aggregation, we need to specify the sort-field
665
665
MultiValuesSourceFieldConfig sortConfig = new MultiValuesSourceFieldConfig .Builder ().setFieldName (sortField ).build ();
666
666
return lineAggregationBuilder .sort (sortConfig );
667
667
}
@@ -698,7 +698,7 @@ private void build() {
698
698
// TSDB provides docs in DESC time order, so we generate the data that way to simplify assertions
699
699
for (int i = t .docCount - 1 ; i >= 0 ; i --) {
700
700
double lat = startLat + i * 0.1 + randomDoubleBetween (-0.1 , 0.1 , false );
701
- double lon = startLon + i * 0.1 + randomDoubleBetween (-0.1 , 0.1 , false );
701
+ double lon = startLon - g * 10 + i * 0.1 + randomDoubleBetween (-0.1 , 0.1 , false );
702
702
GeoPoint point = (t .missingPointFactor > 0 && i % t .missingPointFactor == 0 ) ? null : new GeoPoint (lat , lon );
703
703
Long timestamp = (t .missingTimestampFactor > 0 && i % t .missingTimestampFactor == 0 ) ? null : startTime + 1000L * i ;
704
704
points .add (point );
@@ -723,7 +723,7 @@ private void build() {
723
723
lessThanOrEqualTo (points .size () - deletedAtLeast )
724
724
);
725
725
}
726
- if (t .useTimestamp && t .maxPoints < t .docCount ) {
726
+ if (t .useTimeSeriesAggregation && t .maxPoints < t .docCount ) {
727
727
// The aggregation will simplify the line in reverse order, so we need to anticipate the same simplification in the
728
728
// tests
729
729
TestGeometrySimplifierMonitor monitor = new TestGeometrySimplifierMonitor ();
@@ -738,7 +738,7 @@ private void build() {
738
738
expectedAggSortValues .put (groups [g ], line .sortValues );
739
739
} else {
740
740
// The aggregation will NOT simplify the line, so we should only anticipate the removal of invalid documents
741
- int pointCount = Math . min (t .maxPoints , expectedAggPointsList .size ()); // possible truncation if !useTimestampField
741
+ int pointCount = min (t .maxPoints , expectedAggPointsList .size ()); // possible truncation if !useTimestampField
742
742
int offset = t .sortOrder == SortOrder .DESC ? 0 : Math .max (0 , expectedAggPointsList .size () - pointCount );
743
743
long [] xp = new long [pointCount ];
744
744
double [] xv = new double [pointCount ];
@@ -771,13 +771,13 @@ private ArrayList<Long> timestampsForGroup(int g) {
771
771
772
772
private record TestTSAssertionResults (
773
773
MultiBucketsAggregation ts ,
774
- boolean useTimestampField ,
774
+ boolean useTimeSeriesAggregation ,
775
775
String [] groups ,
776
776
Map <String , long []> expectedAggPoints ,
777
777
Map <String , double []> expectedAggSortValues
778
778
) {
779
779
private TestTSAssertionResults (MultiBucketsAggregation ts , TestConfig testConfig , TestData testData ) {
780
- this (ts , testConfig .useTimestamp , testData .groups , testData .expectedAggPoints , testData .expectedAggSortValues );
780
+ this (ts , testConfig .useTimeSeriesAggregation , testData .groups , testData .expectedAggPoints , testData .expectedAggSortValues );
781
781
}
782
782
}
783
783
@@ -853,7 +853,7 @@ private void testAggregator(SortOrder sortOrder) throws IOException {
853
853
points [i ] = lonLat ;
854
854
sortValues [i ] = i ;
855
855
}
856
- int lineSize = Math . min (numPoints , size );
856
+ int lineSize = min (numPoints , size );
857
857
// re-sort line to be ascending
858
858
long [] linePoints = Arrays .copyOf (points , lineSize );
859
859
double [] lineSorts = Arrays .copyOf (sortValues , lineSize );
@@ -942,12 +942,12 @@ private <A extends MultiBucketsAggregation, C extends Aggregator> void testCase(
942
942
if (timeSeries ) {
943
943
fieldTypes .add (TimeSeriesIdFieldMapper .FIELD_TYPE );
944
944
fieldTypes .add (new DateFieldMapper .DateFieldType ("@timestamp" ));
945
- fieldTypes .add (new DateFieldMapper .DateFieldType ("time_field" ));
946
945
var metricType = randomBoolean () ? POSITION : null ; // metric type does not affect geo_line behaviour
947
946
fieldTypes .add (new GeoPointFieldMapper .GeoPointFieldType ("value_field" , metricType , TIME_SERIES ));
948
947
} else {
949
948
fieldTypes .add (new GeoPointFieldMapper .GeoPointFieldType ("value_field" ));
950
949
}
950
+ fieldTypes .add (new DateFieldMapper .DateFieldType ("time_field" ));
951
951
fieldTypes .add (new KeywordFieldMapper .KeywordFieldType ("group_id" , false , true , Collections .emptyMap ()));
952
952
fieldTypes .add (new NumberFieldMapper .NumberFieldType ("sort_field" , NumberFieldMapper .NumberType .LONG ));
953
953
AggTestConfig aggTestConfig = new AggTestConfig (aggregationBuilder , fieldTypes .toArray (new MappedFieldType [0 ]));
0 commit comments