4747import org .elasticsearch .search .suggest .completion .CompletionSuggestion ;
4848import org .elasticsearch .test .ESTestCase ;
4949import org .elasticsearch .transport .RemoteClusterAware ;
50+ import org .elasticsearch .transport .RemoteClusterService ;
5051import org .junit .Before ;
5152
5253import java .util .ArrayList ;
6465import java .util .concurrent .TimeUnit ;
6566
6667import static org .hamcrest .Matchers .containsInAnyOrder ;
68+ import static org .hamcrest .Matchers .greaterThan ;
69+ import static org .hamcrest .Matchers .greaterThanOrEqualTo ;
6770import static org .hamcrest .Matchers .lessThanOrEqualTo ;
6871
6972public class SearchResponseMergerTests extends ESTestCase {
@@ -241,17 +244,25 @@ public void testMergeProfileResults() throws InterruptedException {
241244 assertEquals (expectedProfile , mergedResponse .getProfileResults ());
242245 }
243246
244- public void testMergeSuggestions () throws InterruptedException {
247+ public void testMergeCompletionSuggestions () throws InterruptedException {
245248 String suggestionName = randomAlphaOfLengthBetween (4 , 8 );
246- boolean skipDuplicates = randomBoolean ();
247249 int size = randomIntBetween (1 , 100 );
248250 SearchResponseMerger searchResponseMerger = new SearchResponseMerger (0 , 0 , 0 , new SearchTimeProvider (0 , 0 , () -> 0 ), flag -> null );
249251 for (int i = 0 ; i < numResponses ; i ++) {
250252 List <Suggest .Suggestion <? extends Suggest .Suggestion .Entry <? extends Suggest .Suggestion .Entry .Option >>> suggestions =
251253 new ArrayList <>();
252- CompletionSuggestion completionSuggestion = new CompletionSuggestion (suggestionName , size , skipDuplicates );
254+ CompletionSuggestion completionSuggestion = new CompletionSuggestion (suggestionName , size , false );
253255 CompletionSuggestion .Entry options = new CompletionSuggestion .Entry (new Text ("suggest" ), 0 , 10 );
254- options .addOption (new CompletionSuggestion .Entry .Option (randomInt (), new Text ("suggestion" ), i , Collections .emptyMap ()));
256+ int docId = randomIntBetween (0 , Integer .MAX_VALUE );
257+ CompletionSuggestion .Entry .Option option = new CompletionSuggestion .Entry .Option (docId ,
258+ new Text (randomAlphaOfLengthBetween (5 , 10 )), i , Collections .emptyMap ());
259+ SearchHit hit = new SearchHit (docId );
260+ ShardId shardId = new ShardId (randomAlphaOfLengthBetween (5 , 10 ), randomAlphaOfLength (10 ),
261+ randomIntBetween (0 , Integer .MAX_VALUE ));
262+ String clusterAlias = randomBoolean () ? "" : randomAlphaOfLengthBetween (5 , 10 );
263+ hit .shard (new SearchShardTarget ("node" , shardId , clusterAlias , OriginalIndices .NONE ));
264+ option .setHit (hit );
265+ options .addOption (option );
255266 completionSuggestion .addTerm (options );
256267 suggestions .add (completionSuggestion );
257268 Suggest suggest = new Suggest (suggestions );
@@ -275,14 +286,69 @@ public void testMergeSuggestions() throws InterruptedException {
275286 mergedResponse .getSuggest ().getSuggestion (suggestionName );
276287 assertEquals (1 , suggestion .getEntries ().size ());
277288 Suggest .Suggestion .Entry <? extends Suggest .Suggestion .Entry .Option > options = suggestion .getEntries ().get (0 );
278- assertEquals (skipDuplicates ? 1 : Math .min (numResponses , size ), options .getOptions ().size ());
289+ assertEquals (Math .min (numResponses , size ), options .getOptions ().size ());
279290 int i = numResponses ;
280291 for (Suggest .Suggestion .Entry .Option option : options ) {
281- assertEquals ("suggestion" , option .getText ().string ());
282292 assertEquals (--i , option .getScore (), 0f );
283293 }
284294 }
285295
296+ public void testMergeCompletionSuggestionsTieBreak () throws InterruptedException {
297+ String suggestionName = randomAlphaOfLengthBetween (4 , 8 );
298+ int size = randomIntBetween (1 , 100 );
299+ SearchResponseMerger searchResponseMerger = new SearchResponseMerger (0 , 0 , 0 , new SearchTimeProvider (0 , 0 , () -> 0 ), flag -> null );
300+ for (int i = 0 ; i < numResponses ; i ++) {
301+ List <Suggest .Suggestion <? extends Suggest .Suggestion .Entry <? extends Suggest .Suggestion .Entry .Option >>> suggestions =
302+ new ArrayList <>();
303+ CompletionSuggestion completionSuggestion = new CompletionSuggestion (suggestionName , size , false );
304+ CompletionSuggestion .Entry options = new CompletionSuggestion .Entry (new Text ("suggest" ), 0 , 10 );
305+ int docId = randomIntBetween (0 , Integer .MAX_VALUE );
306+ CompletionSuggestion .Entry .Option option = new CompletionSuggestion .Entry .Option (docId , new Text ("suggestion" ), 1F ,
307+ Collections .emptyMap ());
308+ SearchHit searchHit = new SearchHit (docId );
309+ searchHit .shard (new SearchShardTarget ("node" , new ShardId ("index" , "uuid" , randomIntBetween (0 , Integer .MAX_VALUE )),
310+ randomBoolean () ? RemoteClusterService .LOCAL_CLUSTER_GROUP_KEY : randomAlphaOfLengthBetween (5 , 10 ), OriginalIndices .NONE ));
311+ option .setHit (searchHit );
312+ options .addOption (option );
313+ completionSuggestion .addTerm (options );
314+ suggestions .add (completionSuggestion );
315+ Suggest suggest = new Suggest (suggestions );
316+ SearchHits searchHits = new SearchHits (new SearchHit [0 ], null , Float .NaN );
317+ InternalSearchResponse internalSearchResponse = new InternalSearchResponse (searchHits , null , suggest , null , false , null , 1 );
318+ SearchResponse searchResponse = new SearchResponse (internalSearchResponse , null , 1 , 1 , 0 , randomLong (),
319+ ShardSearchFailure .EMPTY_ARRAY , SearchResponse .Clusters .EMPTY );
320+ addResponse (searchResponseMerger , searchResponse );
321+ }
322+ awaitResponsesAdded ();
323+ assertEquals (numResponses , searchResponseMerger .numResponses ());
324+ SearchResponse .Clusters clusters = SearchResponseTests .randomClusters ();
325+ SearchResponse mergedResponse = searchResponseMerger .getMergedResponse (clusters );
326+ assertSame (clusters , mergedResponse .getClusters ());
327+ assertEquals (numResponses , mergedResponse .getTotalShards ());
328+ assertEquals (numResponses , mergedResponse .getSuccessfulShards ());
329+ assertEquals (0 , mergedResponse .getSkippedShards ());
330+ assertEquals (0 , mergedResponse .getFailedShards ());
331+ assertEquals (0 , mergedResponse .getShardFailures ().length );
332+ CompletionSuggestion suggestion = mergedResponse .getSuggest ().getSuggestion (suggestionName );
333+ assertEquals (1 , suggestion .getEntries ().size ());
334+ CompletionSuggestion .Entry options = suggestion .getEntries ().get (0 );
335+ assertEquals (Math .min (numResponses , size ), options .getOptions ().size ());
336+ int lastShardId = 0 ;
337+ String lastClusterAlias = null ;
338+ for (CompletionSuggestion .Entry .Option option : options ) {
339+ assertEquals ("suggestion" , option .getText ().string ());
340+ SearchShardTarget shard = option .getHit ().getShard ();
341+ int currentShardId = shard .getShardId ().id ();
342+ assertThat (currentShardId , greaterThanOrEqualTo (lastShardId ));
343+ if (currentShardId == lastShardId ) {
344+ assertThat (shard .getClusterAlias (), greaterThan (lastClusterAlias ));
345+ } else {
346+ lastShardId = currentShardId ;
347+ }
348+ lastClusterAlias = shard .getClusterAlias ();
349+ }
350+ }
351+
286352 public void testMergeAggs () throws InterruptedException {
287353 SearchResponseMerger searchResponseMerger = new SearchResponseMerger (0 , 0 , 0 , new SearchTimeProvider (0 , 0 , () -> 0 ),
288354 flag -> new InternalAggregation .ReduceContext (null , null , flag ));
0 commit comments