1515import  org .elasticsearch .action .search .SearchShardsGroup ;
1616import  org .elasticsearch .action .search .SearchShardsRequest ;
1717import  org .elasticsearch .action .search .SearchShardsResponse ;
18+ import  org .elasticsearch .action .search .SearchType ;
1819import  org .elasticsearch .action .search .TransportSearchShardsAction ;
1920import  org .elasticsearch .blobcache .shared .SharedBlobCacheService ;
2021import  org .elasticsearch .cluster .metadata .DataStream ;
@@ -1100,6 +1101,119 @@ public void testCanMatchSkipsPartiallyMountedIndicesWhenFrozenNodesUnavailable()
11001101        }
11011102    }
11021103
1104+     public  void  testTimestampAsAlias () throws  Exception  {
1105+         doTestCoordRewriteWithAliasField ("@timestamp" );
1106+     }
1107+ 
1108+     public  void  testEventIngestedAsAlias () throws  Exception  {
1109+         doTestCoordRewriteWithAliasField ("event.ingested" );
1110+     }
1111+ 
1112+     private  void  doTestCoordRewriteWithAliasField (String  aliasFieldName ) throws  Exception  {
1113+         internalCluster ().startMasterOnlyNode ();
1114+         internalCluster ().startCoordinatingOnlyNode (Settings .EMPTY );
1115+         final  String  dataNodeHoldingRegularIndex  = internalCluster ().startDataOnlyNode ();
1116+         final  String  dataNodeHoldingSearchableSnapshot  = internalCluster ().startDataOnlyNode ();
1117+ 
1118+         String  timestampFieldName  = randomAlphaOfLengthBetween (3 , 10 );
1119+         String [] indices  = new  String [] { "index-0001" , "index-0002"  };
1120+         for  (String  index  : indices ) {
1121+             Settings  extraSettings  = Settings .builder ()
1122+                 .put (INDEX_ROUTING_REQUIRE_GROUP_SETTING .getConcreteSettingForNamespace ("_name" ).getKey (), dataNodeHoldingRegularIndex )
1123+                 .build ();
1124+ 
1125+             assertAcked (
1126+                 indicesAdmin ().prepareCreate (index )
1127+                     .setMapping (
1128+                         XContentFactory .jsonBuilder ()
1129+                             .startObject ()
1130+                             .startObject ("properties" )
1131+ 
1132+                             .startObject (timestampFieldName )
1133+                             .field ("type" , "date" )
1134+                             .endObject ()
1135+ 
1136+                             .startObject (aliasFieldName )
1137+                             .field ("type" , "alias" )
1138+                             .field ("path" , timestampFieldName )
1139+                             .endObject ()
1140+ 
1141+                             .endObject ()
1142+                             .endObject ()
1143+                     )
1144+                     .setSettings (indexSettingsNoReplicas (1 ).put (INDEX_SOFT_DELETES_SETTING .getKey (), true ).put (extraSettings ))
1145+             );
1146+         }
1147+         ensureGreen (indices );
1148+ 
1149+         for  (String  index  : indices ) {
1150+             final  List <IndexRequestBuilder > indexRequestBuilders  = new  ArrayList <>();
1151+             for  (int  i  = 0 ; i  < 10 ; i ++) {
1152+                 indexRequestBuilders .add (prepareIndex (index ).setSource (timestampFieldName , "2024-11-19T08:08:08Z" ));
1153+             }
1154+             indexRandom (true , false , indexRequestBuilders );
1155+ 
1156+             assertThat (
1157+                 indicesAdmin ().prepareForceMerge (index ).setOnlyExpungeDeletes (true ).setFlush (true ).get ().getFailedShards (),
1158+                 equalTo (0 )
1159+             );
1160+             refresh (index );
1161+             forceMerge ();
1162+         }
1163+ 
1164+         final  String  repositoryName  = randomAlphaOfLength (10 ).toLowerCase (Locale .ROOT );
1165+         createRepository (repositoryName , "mock" );
1166+ 
1167+         final  SnapshotId  snapshotId  = createSnapshot (repositoryName , "snapshot-1" , List .of (indices [0 ])).snapshotId ();
1168+         assertAcked (indicesAdmin ().prepareDelete (indices [0 ]));
1169+ 
1170+         // Block the repository for the node holding the searchable snapshot shards 
1171+         // to delay its restore 
1172+         blockDataNode (repositoryName , dataNodeHoldingSearchableSnapshot );
1173+ 
1174+         // Force the searchable snapshot to be allocated in a particular node 
1175+         Settings  restoredIndexSettings  = Settings .builder ()
1176+             .put (INDEX_ROUTING_REQUIRE_GROUP_SETTING .getConcreteSettingForNamespace ("_name" ).getKey (), dataNodeHoldingSearchableSnapshot )
1177+             .build ();
1178+ 
1179+         String  mountedIndex  = indices [0 ] + "-mounted" ;
1180+         final  MountSearchableSnapshotRequest  mountRequest  = new  MountSearchableSnapshotRequest (
1181+             TEST_REQUEST_TIMEOUT ,
1182+             mountedIndex ,
1183+             repositoryName ,
1184+             snapshotId .getName (),
1185+             indices [0 ],
1186+             restoredIndexSettings ,
1187+             Strings .EMPTY_ARRAY ,
1188+             false ,
1189+             randomFrom (MountSearchableSnapshotRequest .Storage .values ())
1190+         );
1191+         client ().execute (MountSearchableSnapshotAction .INSTANCE , mountRequest ).actionGet ();
1192+ 
1193+         // Allow the searchable snapshots to be finally mounted 
1194+         unblockNode (repositoryName , dataNodeHoldingSearchableSnapshot );
1195+         waitUntilRecoveryIsDone (mountedIndex );
1196+         ensureGreen (mountedIndex );
1197+ 
1198+         String [] fieldsToQuery  = new  String [] { timestampFieldName , aliasFieldName  };
1199+         for  (String  fieldName  : fieldsToQuery ) {
1200+             RangeQueryBuilder  rangeQuery  = QueryBuilders .rangeQuery (fieldName ).from ("2024-11-01T00:00:00.000000000Z" , true );
1201+             SearchRequest  request  = new  SearchRequest ().searchType (SearchType .QUERY_THEN_FETCH )
1202+                 .source (new  SearchSourceBuilder ().query (rangeQuery ));
1203+             if  (randomBoolean ()) {
1204+                 // pre_filter_shard_size default to 1 because there are read-only indices in the mix. It does not hurt to force it though. 
1205+                 request .setPreFilterShardSize (1 );
1206+             }
1207+             assertResponse (client ().search (request ), searchResponse  -> {
1208+                 assertThat (searchResponse .getSuccessfulShards (), equalTo (2 ));
1209+                 assertThat (searchResponse .getFailedShards (), equalTo (0 ));
1210+                 assertThat (searchResponse .getSkippedShards (), equalTo (0 ));
1211+                 assertThat (searchResponse .getTotalShards (), equalTo (2 ));
1212+                 assertThat (searchResponse .getHits ().getTotalHits ().value , equalTo (20L ));
1213+             });
1214+         }
1215+     }
1216+ 
11031217    private  void  createIndexWithTimestampAndEventIngested (String  indexName , int  numShards , Settings  extraSettings ) throws  IOException  {
11041218        assertAcked (
11051219            indicesAdmin ().prepareCreate (indexName )
@@ -1148,8 +1262,7 @@ private void createIndexWithOnlyOneTimestampField(String timestampField, String
11481262        ensureGreen (index );
11491263    }
11501264
1151-     private  void  indexDocumentsWithOnlyOneTimestampField (String  timestampField , String  index , int  docCount , String  timestampTemplate )
1152-         throws  Exception  {
1265+     private  void  indexDocumentsWithOnlyOneTimestampField (String  timestampField , String  index , int  docCount , String  timestampTemplate ) {
11531266        final  List <IndexRequestBuilder > indexRequestBuilders  = new  ArrayList <>();
11541267        for  (int  i  = 0 ; i  < docCount ; i ++) {
11551268            indexRequestBuilders .add (
@@ -1173,8 +1286,7 @@ private void indexDocumentsWithOnlyOneTimestampField(String timestampField, Stri
11731286        forceMerge ();
11741287    }
11751288
1176-     private  void  indexDocumentsWithTimestampAndEventIngestedDates (String  indexName , int  docCount , String  timestampTemplate )
1177-         throws  Exception  {
1289+     private  void  indexDocumentsWithTimestampAndEventIngestedDates (String  indexName , int  docCount , String  timestampTemplate ) {
11781290
11791291        final  List <IndexRequestBuilder > indexRequestBuilders  = new  ArrayList <>();
11801292        for  (int  i  = 0 ; i  < docCount ; i ++) {
@@ -1211,7 +1323,7 @@ private void indexDocumentsWithTimestampAndEventIngestedDates(String indexName,
12111323        forceMerge ();
12121324    }
12131325
1214-     private  IndexMetadata  getIndexMetadata (String  indexName ) {
1326+     private  static   IndexMetadata  getIndexMetadata (String  indexName ) {
12151327        return  clusterAdmin ().prepareState (TEST_REQUEST_TIMEOUT )
12161328            .clear ()
12171329            .setMetadata (true )
@@ -1222,7 +1334,7 @@ private IndexMetadata getIndexMetadata(String indexName) {
12221334            .index (indexName );
12231335    }
12241336
1225-     private  void  waitUntilRecoveryIsDone (String  index ) throws  Exception  {
1337+     private  static   void  waitUntilRecoveryIsDone (String  index ) throws  Exception  {
12261338        assertBusy (() -> {
12271339            RecoveryResponse  recoveryResponse  = indicesAdmin ().prepareRecoveries (index ).get ();
12281340            assertThat (recoveryResponse .hasRecoveries (), equalTo (true ));
0 commit comments