Skip to content

Commit b59dae9

Browse files
authored
[CPS] Search with MRT=true (#137701)
Search when MinimizeRoundTrip (MRT) and Cross-Project Search (CPS) are true. This will fan out to call ResolveIndexAction on each resolved LinkedProject. Results are merged and validated based on ignore_unavailable and allow_no_indices. The results are used as the new resolvedIndices when issuing the subsequent search requests. Linked projects will be searched using the original index express.
1 parent fe1bf19 commit b59dae9

File tree

7 files changed

+499
-45
lines changed

7 files changed

+499
-45
lines changed

server/src/internalClusterTest/java/org/elasticsearch/action/search/TransportSearchIT.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ public void testLocalClusterAlias() throws ExecutionException, InterruptedExcept
139139
parentTaskId,
140140
new SearchRequest(),
141141
Strings.EMPTY_ARRAY,
142+
SearchRequest.DEFAULT_INDICES_OPTIONS,
142143
"local",
143144
nowInMillis,
144145
randomBoolean()
@@ -158,6 +159,7 @@ public void testLocalClusterAlias() throws ExecutionException, InterruptedExcept
158159
parentTaskId,
159160
new SearchRequest(),
160161
Strings.EMPTY_ARRAY,
162+
SearchRequest.DEFAULT_INDICES_OPTIONS,
161163
"",
162164
nowInMillis,
163165
randomBoolean()
@@ -205,6 +207,7 @@ public void testAbsoluteStartMillis() throws ExecutionException, InterruptedExce
205207
parentTaskId,
206208
new SearchRequest(),
207209
Strings.EMPTY_ARRAY,
210+
SearchRequest.DEFAULT_INDICES_OPTIONS,
208211
"",
209212
0,
210213
randomBoolean()
@@ -216,6 +219,7 @@ public void testAbsoluteStartMillis() throws ExecutionException, InterruptedExce
216219
parentTaskId,
217220
new SearchRequest(),
218221
Strings.EMPTY_ARRAY,
222+
SearchRequest.DEFAULT_INDICES_OPTIONS,
219223
"",
220224
0,
221225
randomBoolean()
@@ -231,6 +235,7 @@ public void testAbsoluteStartMillis() throws ExecutionException, InterruptedExce
231235
parentTaskId,
232236
new SearchRequest(),
233237
Strings.EMPTY_ARRAY,
238+
SearchRequest.DEFAULT_INDICES_OPTIONS,
234239
"",
235240
0,
236241
randomBoolean()
@@ -279,7 +284,15 @@ public void testFinalReduce() throws ExecutionException, InterruptedException {
279284
{
280285
SearchRequest searchRequest = randomBoolean()
281286
? originalRequest
282-
: SearchRequest.subSearchRequest(taskId, originalRequest, Strings.EMPTY_ARRAY, "remote", nowInMillis, true);
287+
: SearchRequest.subSearchRequest(
288+
taskId,
289+
originalRequest,
290+
Strings.EMPTY_ARRAY,
291+
originalRequest.indicesOptions(),
292+
"remote",
293+
nowInMillis,
294+
true
295+
);
283296
assertResponse(client().search(searchRequest), searchResponse -> {
284297
assertEquals(2, searchResponse.getHits().getTotalHits().value());
285298
InternalAggregations aggregations = searchResponse.getAggregations();
@@ -292,6 +305,7 @@ public void testFinalReduce() throws ExecutionException, InterruptedException {
292305
taskId,
293306
originalRequest,
294307
Strings.EMPTY_ARRAY,
308+
originalRequest.indicesOptions(),
295309
"remote",
296310
nowInMillis,
297311
false

server/src/main/java/org/elasticsearch/action/ResolvedIndices.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,44 @@ public static ResolvedIndices resolveWithPIT(
253253
);
254254
}
255255

256+
/**
257+
* Create a new {@link ResolvedIndices} instance from a Map of Projects to {@link ResolvedIndexExpressions}. This is intended to be
258+
* used for Cross-Project Search (CPS).
259+
*
260+
* @param localIndices this value is set as-is in the resulting ResolvedIndices.
261+
* @param localIndexMetadata this value is set as-is in the resulting ResolvedIndices.
262+
* @param remoteExpressions the map of project names to {@link ResolvedIndexExpressions}. This map is used to create the
263+
* {@link ResolvedIndices#getRemoteClusterIndices()} for the resulting ResolvedIndices. Each project keyed
264+
* in the map is guaranteed to have at least one index for the index expression provided by the user.
265+
* The resulting {@link ResolvedIndices#getRemoteClusterIndices()} will map to the original index expression
266+
* provided by the user. For example, if the user requested "logs" and "project-1" resolved that to "logs-1",
267+
* then the result will map "project-1" to "logs". We rely on the remote search request to expand "logs" back
268+
* to "logs-1".
269+
* @param indicesOptions this value is set as-is in the resulting ResolvedIndices.
270+
*/
271+
public static ResolvedIndices resolveWithIndexExpressions(
272+
OriginalIndices localIndices,
273+
Map<Index, IndexMetadata> localIndexMetadata,
274+
Map<String, ResolvedIndexExpressions> remoteExpressions,
275+
IndicesOptions indicesOptions
276+
) {
277+
Map<String, OriginalIndices> remoteIndices = remoteExpressions.entrySet().stream().collect(HashMap::new, (map, entry) -> {
278+
var indices = entry.getValue().expressions().stream().filter(expression -> {
279+
var resolvedExpressions = expression.localExpressions();
280+
var successfulResolution = resolvedExpressions
281+
.localIndexResolutionResult() == ResolvedIndexExpression.LocalIndexResolutionResult.SUCCESS;
282+
// if the expression is a wildcard, it will be successful even if there are no indices, so filter for no indices
283+
var hasResolvedIndices = resolvedExpressions.indices().isEmpty() == false;
284+
return successfulResolution && hasResolvedIndices;
285+
}).map(ResolvedIndexExpression::original).toArray(String[]::new);
286+
if (indices.length > 0) {
287+
map.put(entry.getKey(), new OriginalIndices(indices, indicesOptions));
288+
}
289+
}, Map::putAll);
290+
291+
return new ResolvedIndices(remoteIndices, localIndices, localIndexMetadata);
292+
}
293+
256294
private static Map<Index, IndexMetadata> resolveLocalIndexMetadata(
257295
Index[] concreteLocalIndices,
258296
ProjectMetadata projectMetadata,

server/src/main/java/org/elasticsearch/action/search/SearchRequest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public void setProjectRouting(@Nullable String projectRouting) {
196196
* @param parentTaskId the parent taskId of the original search request
197197
* @param originalSearchRequest the original search request
198198
* @param indices the indices to search against
199+
* @param indicesOptions the indicesOptions to search with
199200
* @param clusterAlias the alias to prefix index names with in the returned search results
200201
* @param absoluteStartMillis the absolute start time to be used on the remote clusters to ensure that the same value is used
201202
* @param finalReduce whether the reduction should be final or not
@@ -204,6 +205,7 @@ static SearchRequest subSearchRequest(
204205
TaskId parentTaskId,
205206
SearchRequest originalSearchRequest,
206207
String[] indices,
208+
IndicesOptions indicesOptions,
207209
String clusterAlias,
208210
long absoluteStartMillis,
209211
boolean finalReduce
@@ -217,6 +219,7 @@ static SearchRequest subSearchRequest(
217219
}
218220
final SearchRequest request = new SearchRequest(originalSearchRequest, indices, clusterAlias, absoluteStartMillis, finalReduce);
219221
request.setParentTask(parentTaskId);
222+
request.indicesOptions(indicesOptions);
220223
return request;
221224
}
222225

@@ -414,8 +417,8 @@ boolean isFinalReduce() {
414417
/**
415418
* Returns the current time in milliseconds from the time epoch, to be used for the execution of this search request. Used to
416419
* ensure that the same value, determined by the coordinating node, is used on all nodes involved in the execution of the search
417-
* request. When created through {@link #subSearchRequest(TaskId, SearchRequest, String[], String, long, boolean)}, this method returns
418-
* the provided current time, otherwise it will return {@link System#currentTimeMillis()}.
420+
* request. When created through {@link #subSearchRequest(TaskId, SearchRequest, String[], IndicesOptions, String, long, boolean)},
421+
* this method returns the provided current time, otherwise it will return {@link System#currentTimeMillis()}.
419422
*/
420423
long getOrCreateAbsoluteStartMillis() {
421424
return absoluteStartMillis == DEFAULT_ABSOLUTE_START_MILLIS ? System.currentTimeMillis() : absoluteStartMillis;

0 commit comments

Comments
 (0)