15
15
import org .elasticsearch .action .search .SearchShardsGroup ;
16
16
import org .elasticsearch .action .search .SearchShardsRequest ;
17
17
import org .elasticsearch .action .search .SearchShardsResponse ;
18
+ import org .elasticsearch .action .search .SearchType ;
18
19
import org .elasticsearch .action .search .TransportSearchShardsAction ;
19
20
import org .elasticsearch .blobcache .shared .SharedBlobCacheService ;
20
21
import org .elasticsearch .cluster .metadata .DataStream ;
@@ -1100,6 +1101,119 @@ public void testCanMatchSkipsPartiallyMountedIndicesWhenFrozenNodesUnavailable()
1100
1101
}
1101
1102
}
1102
1103
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
+
1103
1217
private void createIndexWithTimestampAndEventIngested (String indexName , int numShards , Settings extraSettings ) throws IOException {
1104
1218
assertAcked (
1105
1219
indicesAdmin ().prepareCreate (indexName )
@@ -1148,8 +1262,7 @@ private void createIndexWithOnlyOneTimestampField(String timestampField, String
1148
1262
ensureGreen (index );
1149
1263
}
1150
1264
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 ) {
1153
1266
final List <IndexRequestBuilder > indexRequestBuilders = new ArrayList <>();
1154
1267
for (int i = 0 ; i < docCount ; i ++) {
1155
1268
indexRequestBuilders .add (
@@ -1173,8 +1286,7 @@ private void indexDocumentsWithOnlyOneTimestampField(String timestampField, Stri
1173
1286
forceMerge ();
1174
1287
}
1175
1288
1176
- private void indexDocumentsWithTimestampAndEventIngestedDates (String indexName , int docCount , String timestampTemplate )
1177
- throws Exception {
1289
+ private void indexDocumentsWithTimestampAndEventIngestedDates (String indexName , int docCount , String timestampTemplate ) {
1178
1290
1179
1291
final List <IndexRequestBuilder > indexRequestBuilders = new ArrayList <>();
1180
1292
for (int i = 0 ; i < docCount ; i ++) {
@@ -1211,7 +1323,7 @@ private void indexDocumentsWithTimestampAndEventIngestedDates(String indexName,
1211
1323
forceMerge ();
1212
1324
}
1213
1325
1214
- private IndexMetadata getIndexMetadata (String indexName ) {
1326
+ private static IndexMetadata getIndexMetadata (String indexName ) {
1215
1327
return clusterAdmin ().prepareState (TEST_REQUEST_TIMEOUT )
1216
1328
.clear ()
1217
1329
.setMetadata (true )
@@ -1222,7 +1334,7 @@ private IndexMetadata getIndexMetadata(String indexName) {
1222
1334
.index (indexName );
1223
1335
}
1224
1336
1225
- private void waitUntilRecoveryIsDone (String index ) throws Exception {
1337
+ private static void waitUntilRecoveryIsDone (String index ) throws Exception {
1226
1338
assertBusy (() -> {
1227
1339
RecoveryResponse recoveryResponse = indicesAdmin ().prepareRecoveries (index ).get ();
1228
1340
assertThat (recoveryResponse .hasRecoveries (), equalTo (true ));
0 commit comments