3232import org .apache .lucene .search .Sort ;
3333import org .apache .lucene .search .SortField ;
3434import org .apache .lucene .search .SortedNumericSortField ;
35+ import org .apache .lucene .search .SortedSetSortField ;
3536import org .apache .lucene .store .Directory ;
3637import org .apache .lucene .util .BytesRef ;
3738import org .elasticsearch .cluster .metadata .DataStream ;
@@ -1302,6 +1303,79 @@ public int get(int docId) {
13021303 }
13031304 }
13041305
1306+ public void testEncodeRangeWithSortedSetPrimarySortField () throws Exception {
1307+ String timestampField = "@timestamp" ;
1308+ String hostnameField = "host.name" ;
1309+ long baseTimestamp = 1704067200000L ;
1310+
1311+ var config = getTimeSeriesIndexWriterConfig (hostnameField , true , timestampField );
1312+ try (var dir = newDirectory (); var iw = new IndexWriter (dir , config )) {
1313+
1314+ int numDocs = 512 + random ().nextInt (512 );
1315+ int numHosts = numDocs / 20 ;
1316+
1317+ for (int i = 0 ; i < numDocs ; i ++) {
1318+ var d = new Document ();
1319+ int batchIndex = i / numHosts ;
1320+ {
1321+ String hostName = String .format (Locale .ROOT , "host-%03d" , batchIndex );
1322+ d .add (new SortedSetDocValuesField (hostnameField , new BytesRef (hostName )));
1323+ }
1324+ {
1325+ String hostName = String .format (Locale .ROOT , "host-%03d" , batchIndex + 1 );
1326+ d .add (new SortedSetDocValuesField (hostnameField , new BytesRef (hostName )));
1327+ }
1328+ // Index sorting doesn't work with NumericDocValuesField:
1329+ long timestamp = baseTimestamp + (1000L * i );
1330+ d .add (new SortedNumericDocValuesField (timestampField , timestamp ));
1331+ iw .addDocument (d );
1332+ if (i % 100 == 0 ) {
1333+ iw .commit ();
1334+ }
1335+ }
1336+ iw .commit ();
1337+ iw .forceMerge (1 );
1338+
1339+ try (var reader = DirectoryReader .open (iw )) {
1340+ assertEquals (1 , reader .leaves ().size ());
1341+ assertEquals (numDocs , reader .maxDoc ());
1342+ var leaf = reader .leaves ().get (0 ).reader ();
1343+ var hostNameDV = leaf .getSortedSetDocValues (hostnameField );
1344+ assertNotNull (hostNameDV );
1345+ var timestampDV = DocValues .unwrapSingleton (leaf .getSortedNumericDocValues (timestampField ));
1346+ assertNotNull (timestampDV );
1347+ for (int i = 0 ; i < numDocs ; i ++) {
1348+ assertEquals (i , hostNameDV .nextDoc ());
1349+
1350+ int batchIndex = i / numHosts ;
1351+ assertEquals (2 , hostNameDV .docValueCount ());
1352+
1353+ long firstOrd = hostNameDV .nextOrd ();
1354+ assertEquals (batchIndex , firstOrd );
1355+ String expectedFirstHostName = String .format (Locale .ROOT , "host-%03d" , batchIndex );
1356+ String actualFirstHostName = hostNameDV .lookupOrd (firstOrd ).utf8ToString ();
1357+ assertEquals (expectedFirstHostName , actualFirstHostName );
1358+
1359+ batchIndex ++;
1360+ long secondOrd = hostNameDV .nextOrd ();
1361+ assertEquals (batchIndex , secondOrd );
1362+ String expectedSecondHostName = String .format (Locale .ROOT , "host-%03d" , batchIndex );
1363+ String actualSecondHostName = hostNameDV .lookupOrd (secondOrd ).utf8ToString ();
1364+ assertEquals (expectedSecondHostName , actualSecondHostName );
1365+
1366+ assertEquals (i , timestampDV .nextDoc ());
1367+ long timestamp = timestampDV .longValue ();
1368+ long lowerBound = baseTimestamp ;
1369+ long upperBound = baseTimestamp + (1000L * numDocs );
1370+ assertTrue (
1371+ "unexpected timestamp [" + timestamp + "], expected between [" + lowerBound + "] and [" + upperBound + "]" ,
1372+ timestamp >= lowerBound && timestamp < upperBound
1373+ );
1374+ }
1375+ }
1376+ }
1377+ }
1378+
13051379 private static BaseDenseNumericValues getBaseDenseNumericValues (LeafReader leafReader , String field ) throws IOException {
13061380 return (BaseDenseNumericValues ) DocValues .unwrapSingleton (leafReader .getSortedNumericDocValues (field ));
13071381 }
@@ -1315,11 +1389,15 @@ private static BaseSortedDocValues getBaseSortedDocValues(LeafReader leafReader,
13151389 }
13161390
13171391 private IndexWriterConfig getTimeSeriesIndexWriterConfig (String hostnameField , String timestampField ) {
1392+ return getTimeSeriesIndexWriterConfig (hostnameField , false , timestampField );
1393+ }
1394+
1395+ private IndexWriterConfig getTimeSeriesIndexWriterConfig (String hostnameField , boolean multiValued , String timestampField ) {
13181396 var config = new IndexWriterConfig ();
13191397 if (hostnameField != null ) {
13201398 config .setIndexSort (
13211399 new Sort (
1322- new SortField (hostnameField , SortField .Type .STRING , false ),
1400+ multiValued ? new SortedSetSortField ( hostnameField , false ) : new SortField (hostnameField , SortField .Type .STRING , false ),
13231401 new SortedNumericSortField (timestampField , SortField .Type .LONG , true )
13241402 )
13251403 );
0 commit comments