Add support for retrieving request executionDuration.

Original Pull Request #2991
Closes #2986
This commit is contained in:
El-Harrougui MOHAMED 2024-10-22 05:11:57 +01:00 committed by GitHub
parent 172933af8e
commit d2ab03e6a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 121 additions and 68 deletions

View File

@ -81,7 +81,7 @@ When a document is retrieved with the methods of the `DocumentOperations` inter
When searching with the methods of the `SearchOperations` interface, additional information is available for each entity, for example the _score_ or the _sortValues_ of the found entity. When searching with the methods of the `SearchOperations` interface, additional information is available for each entity, for example the _score_ or the _sortValues_ of the found entity.
In order to return this information, each entity is wrapped in a `SearchHit` object that contains this entity-specific additional information. In order to return this information, each entity is wrapped in a `SearchHit` object that contains this entity-specific additional information.
These `SearchHit` objects themselves are returned within a `SearchHits` object which additionally contains informations about the whole search like the _maxScore_ or requested aggregations. These `SearchHit` objects themselves are returned within a `SearchHits` object which additionally contains informations about the whole search like the _maxScore_ or requested aggregations or the execution duration it took to complete the request.
The following classes and interfaces are now available: The following classes and interfaces are now available:
.SearchHit<T> .SearchHit<T>

View File

@ -50,6 +50,7 @@ import org.springframework.util.Assert;
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.4 * @since 4.4
*/ */
final class DocumentAdapters { final class DocumentAdapters {
@ -74,7 +75,7 @@ final class DocumentAdapters {
Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>(); Map<String, SearchDocumentResponse> innerHits = new LinkedHashMap<>();
hit.innerHits().forEach((name, innerHitsResult) -> { hit.innerHits().forEach((name, innerHitsResult) -> {
// noinspection ReturnOfNull // noinspection ReturnOfNull
innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, null, null, innerHits.put(name, SearchDocumentResponseBuilder.from(innerHitsResult.hits(), null, null, null, 0, null, null,
searchDocument -> null, jsonpMapper)); searchDocument -> null, jsonpMapper));
}); });

View File

@ -29,6 +29,7 @@ import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.elasticsearch.core.search.TotalHits; import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.JsonpMapper;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -56,6 +57,7 @@ import org.springframework.util.CollectionUtils;
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.4 * @since 4.4
*/ */
class SearchDocumentResponseBuilder { class SearchDocumentResponseBuilder {
@ -83,8 +85,10 @@ class SearchDocumentResponseBuilder {
Map<String, List<Suggestion<EntityAsMap>>> suggest = responseBody.suggest(); Map<String, List<Suggestion<EntityAsMap>>> suggest = responseBody.suggest();
var pointInTimeId = responseBody.pitId(); var pointInTimeId = responseBody.pitId();
var shards = responseBody.shards(); var shards = responseBody.shards();
var executionDurationInMillis = responseBody.took();
return from(hitsMetadata, shards, scrollId, pointInTimeId, aggregations, suggest, entityCreator, jsonpMapper); return from(hitsMetadata, shards, scrollId, pointInTimeId, executionDurationInMillis, aggregations, suggest,
entityCreator, jsonpMapper);
} }
/** /**
@ -109,8 +113,10 @@ class SearchDocumentResponseBuilder {
var aggregations = response.aggregations(); var aggregations = response.aggregations();
var suggest = response.suggest(); var suggest = response.suggest();
var pointInTimeId = response.pitId(); var pointInTimeId = response.pitId();
var executionDurationInMillis = response.took();
return from(hitsMetadata, shards, scrollId, pointInTimeId, aggregations, suggest, entityCreator, jsonpMapper); return from(hitsMetadata, shards, scrollId, pointInTimeId, executionDurationInMillis, aggregations, suggest,
entityCreator, jsonpMapper);
} }
/** /**
@ -127,7 +133,7 @@ class SearchDocumentResponseBuilder {
* @return the {@link SearchDocumentResponse} * @return the {@link SearchDocumentResponse}
*/ */
public static <T> SearchDocumentResponse from(HitsMetadata<?> hitsMetadata, @Nullable ShardStatistics shards, public static <T> SearchDocumentResponse from(HitsMetadata<?> hitsMetadata, @Nullable ShardStatistics shards,
@Nullable String scrollId, @Nullable String pointInTimeId, @Nullable Map<String, Aggregate> aggregations, @Nullable String scrollId, @Nullable String pointInTimeId, long executionDurationInMillis, @Nullable Map<String, Aggregate> aggregations,
Map<String, List<Suggestion<EntityAsMap>>> suggestES, SearchDocumentResponse.EntityCreator<T> entityCreator, Map<String, List<Suggestion<EntityAsMap>>> suggestES, SearchDocumentResponse.EntityCreator<T> entityCreator,
JsonpMapper jsonpMapper) { JsonpMapper jsonpMapper) {
@ -151,6 +157,8 @@ class SearchDocumentResponseBuilder {
float maxScore = hitsMetadata.maxScore() != null ? hitsMetadata.maxScore().floatValue() : Float.NaN; float maxScore = hitsMetadata.maxScore() != null ? hitsMetadata.maxScore().floatValue() : Float.NaN;
Duration executionDuration = Duration.ofMillis(executionDurationInMillis);
List<SearchDocument> searchDocuments = new ArrayList<>(); List<SearchDocument> searchDocuments = new ArrayList<>();
for (Hit<?> hit : hitsMetadata.hits()) { for (Hit<?> hit : hitsMetadata.hits()) {
searchDocuments.add(DocumentAdapters.from(hit, jsonpMapper)); searchDocuments.add(DocumentAdapters.from(hit, jsonpMapper));
@ -163,7 +171,7 @@ class SearchDocumentResponseBuilder {
SearchShardStatistics shardStatistics = shards != null ? shardsFrom(shards) : null; SearchShardStatistics shardStatistics = shards != null ? shardsFrom(shards) : null;
return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, scrollId, pointInTimeId, searchDocuments, return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, executionDuration, scrollId, pointInTimeId, searchDocuments,
aggregationsContainer, suggest, shardStatistics); aggregationsContainer, suggest, shardStatistics);
} }

View File

@ -17,6 +17,8 @@ package org.springframework.data.elasticsearch.core;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import java.time.Duration;
import org.springframework.data.elasticsearch.core.suggest.response.Suggest; import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -25,6 +27,7 @@ import org.springframework.lang.Nullable;
* *
* @param <T> the result data class. * @param <T> the result data class.
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Mohamed El Harrougui
* @since 4.4 * @since 4.4
*/ */
public interface ReactiveSearchHits<T> { public interface ReactiveSearchHits<T> {
@ -37,6 +40,11 @@ public interface ReactiveSearchHits<T> {
float getMaxScore(); float getMaxScore();
/**
* @return the execution duration it took to complete the request
*/
Duration getExecutionDuration();
/** /**
* @return the {@link SearchHit}s from the search result. * @return the {@link SearchHit}s from the search result.
*/ */

View File

@ -17,11 +17,14 @@ package org.springframework.data.elasticsearch.core;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import java.time.Duration;
import org.springframework.data.elasticsearch.core.suggest.response.Suggest; import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Mohamed El Harrougui
* @since 4.4 * @since 4.4
*/ */
public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> { public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> {
@ -58,6 +61,11 @@ public class ReactiveSearchHitsImpl<T> implements ReactiveSearchHits<T> {
return delegate.getMaxScore(); return delegate.getMaxScore();
} }
@Override
public Duration getExecutionDuration() {
return delegate.getExecutionDuration();
}
@Override @Override
public boolean hasSearchHits() { public boolean hasSearchHits() {
return delegate.hasSearchHits(); return delegate.hasSearchHits();

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -47,6 +48,7 @@ import org.springframework.util.Assert;
* @author Sascha Woo * @author Sascha Woo
* @author Jakob Hoeper * @author Jakob Hoeper
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.0 * @since 4.0
*/ */
public class SearchHitMapping<T> { public class SearchHitMapping<T> {
@ -87,6 +89,7 @@ public class SearchHitMapping<T> {
long totalHits = searchDocumentResponse.getTotalHits(); long totalHits = searchDocumentResponse.getTotalHits();
SearchShardStatistics shardStatistics = searchDocumentResponse.getSearchShardStatistics(); SearchShardStatistics shardStatistics = searchDocumentResponse.getSearchShardStatistics();
float maxScore = searchDocumentResponse.getMaxScore(); float maxScore = searchDocumentResponse.getMaxScore();
Duration executionDuration = searchDocumentResponse.getExecutionDuration();
String scrollId = searchDocumentResponse.getScrollId(); String scrollId = searchDocumentResponse.getScrollId();
String pointInTimeId = searchDocumentResponse.getPointInTimeId(); String pointInTimeId = searchDocumentResponse.getPointInTimeId();
@ -104,8 +107,8 @@ public class SearchHitMapping<T> {
Suggest suggest = searchDocumentResponse.getSuggest(); Suggest suggest = searchDocumentResponse.getSuggest();
mapHitsInCompletionSuggestion(suggest); mapHitsInCompletionSuggestion(suggest);
return new SearchHitsImpl<>(totalHits, totalHitsRelation, maxScore, scrollId, pointInTimeId, searchHits, return new SearchHitsImpl<>(totalHits, totalHitsRelation, maxScore, executionDuration, scrollId, pointInTimeId,
aggregations, suggest, shardStatistics); searchHits, aggregations, suggest, shardStatistics);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -238,6 +241,7 @@ public class SearchHitMapping<T> {
return new SearchHitsImpl<>(searchHits.getTotalHits(), return new SearchHitsImpl<>(searchHits.getTotalHits(),
searchHits.getTotalHitsRelation(), searchHits.getTotalHitsRelation(),
searchHits.getMaxScore(), searchHits.getMaxScore(),
searchHits.getExecutionDuration(),
scrollId, scrollId,
searchHits.getPointInTimeId(), searchHits.getPointInTimeId(),
convertedSearchHits, convertedSearchHits,

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.time.Duration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -28,6 +29,7 @@ import org.springframework.lang.Nullable;
* @param <T> the result data class. * @param <T> the result data class.
* @author Sascha Woo * @author Sascha Woo
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.0 * @since 4.0
*/ */
public interface SearchHits<T> extends Streamable<SearchHit<T>> { public interface SearchHits<T> extends Streamable<SearchHit<T>> {
@ -43,6 +45,11 @@ public interface SearchHits<T> extends Streamable<SearchHit<T>> {
*/ */
float getMaxScore(); float getMaxScore();
/**
* @return the execution duration it took to complete the request
*/
Duration getExecutionDuration();
/** /**
* @param index position in List. * @param index position in List.
* @return the {@link SearchHit} at position {index} * @return the {@link SearchHit} at position {index}

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.time.Duration;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -30,6 +31,7 @@ import org.springframework.util.Assert;
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Sascha Woo * @author Sascha Woo
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.0 * @since 4.0
*/ */
public class SearchHitsImpl<T> implements SearchScrollHits<T> { public class SearchHitsImpl<T> implements SearchScrollHits<T> {
@ -37,6 +39,7 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
private final long totalHits; private final long totalHits;
private final TotalHitsRelation totalHitsRelation; private final TotalHitsRelation totalHitsRelation;
private final float maxScore; private final float maxScore;
private final Duration executionDuration;
@Nullable private final String scrollId; @Nullable private final String scrollId;
private final List<? extends SearchHit<T>> searchHits; private final List<? extends SearchHit<T>> searchHits;
private final Lazy<List<SearchHit<T>>> unmodifiableSearchHits; private final Lazy<List<SearchHit<T>>> unmodifiableSearchHits;
@ -49,12 +52,13 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
* @param totalHits the number of total hits for the search * @param totalHits the number of total hits for the search
* @param totalHitsRelation the relation {@see TotalHitsRelation}, must not be {@literal null} * @param totalHitsRelation the relation {@see TotalHitsRelation}, must not be {@literal null}
* @param maxScore the maximum score * @param maxScore the maximum score
* @param executionDuration the execution duration it took to complete the request
* @param scrollId the scroll id if available * @param scrollId the scroll id if available
* @param searchHits must not be {@literal null} * @param searchHits must not be {@literal null}
* @param aggregations the aggregations if available * @param aggregations the aggregations if available
*/ */
public SearchHitsImpl(long totalHits, TotalHitsRelation totalHitsRelation, float maxScore, @Nullable String scrollId, public SearchHitsImpl(long totalHits, TotalHitsRelation totalHitsRelation, float maxScore, Duration executionDuration,
@Nullable String pointInTimeId, List<? extends SearchHit<T>> searchHits, @Nullable String scrollId, @Nullable String pointInTimeId, List<? extends SearchHit<T>> searchHits,
@Nullable AggregationsContainer<?> aggregations, @Nullable Suggest suggest, @Nullable AggregationsContainer<?> aggregations, @Nullable Suggest suggest,
@Nullable SearchShardStatistics searchShardStatistics) { @Nullable SearchShardStatistics searchShardStatistics) {
@ -63,6 +67,7 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
this.totalHits = totalHits; this.totalHits = totalHits;
this.totalHitsRelation = totalHitsRelation; this.totalHitsRelation = totalHitsRelation;
this.maxScore = maxScore; this.maxScore = maxScore;
this.executionDuration = executionDuration;
this.scrollId = scrollId; this.scrollId = scrollId;
this.pointInTimeId = pointInTimeId; this.pointInTimeId = pointInTimeId;
this.searchHits = searchHits; this.searchHits = searchHits;
@ -88,6 +93,11 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
return maxScore; return maxScore;
} }
@Override
public Duration getExecutionDuration() {
return executionDuration;
}
@Override @Override
@Nullable @Nullable
public String getScrollId() { public String getScrollId() {
@ -133,6 +143,7 @@ public class SearchHitsImpl<T> implements SearchScrollHits<T> {
"totalHits=" + totalHits + // "totalHits=" + totalHits + //
", totalHitsRelation=" + totalHitsRelation + // ", totalHitsRelation=" + totalHitsRelation + //
", maxScore=" + maxScore + // ", maxScore=" + maxScore + //
", executionDuration=" + executionDuration + //
", scrollId='" + scrollId + '\'' + // ", scrollId='" + scrollId + '\'' + //
", pointInTimeId='" + pointInTimeId + '\'' + // ", pointInTimeId='" + pointInTimeId + '\'' + //
", searchHits={" + searchHits.size() + " elements}" + // ", searchHits={" + searchHits.size() + " elements}" + //

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.time.Duration;
import org.springframework.data.util.CloseableIterator; import org.springframework.data.util.CloseableIterator;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -23,6 +25,7 @@ import org.springframework.lang.Nullable;
* {@link java.util.stream.Stream}. * {@link java.util.stream.Stream}.
* *
* @author Sascha Woo * @author Sascha Woo
* @author Mohamed El Harrougui
* @param <T> * @param <T>
* @since 4.0 * @since 4.0
*/ */
@ -39,6 +42,11 @@ public interface SearchHitsIterator<T> extends CloseableIterator<SearchHit<T>> {
*/ */
float getMaxScore(); float getMaxScore();
/**
* @return the execution duration it took to complete the request
*/
Duration getExecutionDuration();
/** /**
* @return the number of total hits. * @return the number of total hits.
*/ */

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.time.Duration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
@ -31,6 +32,7 @@ import org.springframework.util.Assert;
* *
* @author Mark Paluch * @author Mark Paluch
* @author Sascha Woo * @author Sascha Woo
* @author Mohamed El Harrougui
* @since 3.2 * @since 3.2
*/ */
abstract class StreamQueries { abstract class StreamQueries {
@ -56,6 +58,7 @@ abstract class StreamQueries {
AggregationsContainer<?> aggregations = searchHits.getAggregations(); AggregationsContainer<?> aggregations = searchHits.getAggregations();
float maxScore = searchHits.getMaxScore(); float maxScore = searchHits.getMaxScore();
Duration executionDuration = searchHits.getExecutionDuration();
long totalHits = searchHits.getTotalHits(); long totalHits = searchHits.getTotalHits();
TotalHitsRelation totalHitsRelation = searchHits.getTotalHitsRelation(); TotalHitsRelation totalHitsRelation = searchHits.getTotalHitsRelation();
@ -86,6 +89,11 @@ abstract class StreamQueries {
return maxScore; return maxScore;
} }
@Override
public Duration getExecutionDuration() {
return executionDuration;
}
@Override @Override
public long getTotalHits() { public long getTotalHits() {
return totalHits; return totalHits;

View File

@ -15,6 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core.document; package org.springframework.data.elasticsearch.core.document;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
@ -29,6 +30,7 @@ import org.springframework.lang.Nullable;
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 4.0 * @since 4.0
*/ */
public class SearchDocumentResponse { public class SearchDocumentResponse {
@ -36,6 +38,7 @@ public class SearchDocumentResponse {
private final long totalHits; private final long totalHits;
private final String totalHitsRelation; private final String totalHitsRelation;
private final float maxScore; private final float maxScore;
private final Duration executionDuration;
@Nullable private final String scrollId; @Nullable private final String scrollId;
private final List<SearchDocument> searchDocuments; private final List<SearchDocument> searchDocuments;
@Nullable private final AggregationsContainer<?> aggregations; @Nullable private final AggregationsContainer<?> aggregations;
@ -44,13 +47,14 @@ public class SearchDocumentResponse {
@Nullable String pointInTimeId; @Nullable String pointInTimeId;
@Nullable private final SearchShardStatistics searchShardStatistics; @Nullable private final SearchShardStatistics searchShardStatistics;
public SearchDocumentResponse(long totalHits, String totalHitsRelation, float maxScore, @Nullable String scrollId, public SearchDocumentResponse(long totalHits, String totalHitsRelation, float maxScore, Duration executionDuration,
@Nullable String pointInTimeId, List<SearchDocument> searchDocuments, @Nullable String scrollId, @Nullable String pointInTimeId, List<SearchDocument> searchDocuments,
@Nullable AggregationsContainer<?> aggregationsContainer, @Nullable Suggest suggest, @Nullable AggregationsContainer<?> aggregationsContainer, @Nullable Suggest suggest,
@Nullable SearchShardStatistics searchShardStatistics) { @Nullable SearchShardStatistics searchShardStatistics) {
this.totalHits = totalHits; this.totalHits = totalHits;
this.totalHitsRelation = totalHitsRelation; this.totalHitsRelation = totalHitsRelation;
this.maxScore = maxScore; this.maxScore = maxScore;
this.executionDuration = executionDuration;
this.scrollId = scrollId; this.scrollId = scrollId;
this.pointInTimeId = pointInTimeId; this.pointInTimeId = pointInTimeId;
this.searchDocuments = searchDocuments; this.searchDocuments = searchDocuments;
@ -71,6 +75,10 @@ public class SearchDocumentResponse {
return maxScore; return maxScore;
} }
public Duration getExecutionDuration() {
return executionDuration;
}
@Nullable @Nullable
public String getScrollId() { public String getScrollId() {
return scrollId; return scrollId;

View File

@ -44,6 +44,7 @@ import com.google.common.collect.ImmutableMap;
* *
* @author Sébastien Comeau * @author Sébastien Comeau
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
* @since 5.2 * @since 5.2
*/ */
class SearchDocumentResponseBuilderUnitTests { class SearchDocumentResponseBuilderUnitTests {
@ -54,35 +55,21 @@ class SearchDocumentResponseBuilderUnitTests {
void shouldGetPhraseSuggestion() throws JSONException { void shouldGetPhraseSuggestion() throws JSONException {
// arrange // arrange
final var hitsMetadata = new HitsMetadata.Builder<EntityAsMap>() final var hitsMetadata = new HitsMetadata.Builder<EntityAsMap>()
.total(total -> total .total(total -> total.value(0).relation(TotalHitsRelation.Eq)).hits(new ArrayList<>()).build();
.value(0)
.relation(TotalHitsRelation.Eq))
.hits(new ArrayList<>())
.build();
final var suggestionTest = new Suggestion.Builder<EntityAsMap>() final var suggestionTest = new Suggestion.Builder<EntityAsMap>().phrase(phrase -> phrase.text("National").offset(0)
.phrase(phrase -> phrase
.text("National")
.offset(0)
.length(8) .length(8)
.options(option -> option .options(
.text("nations") option -> option.text("nations").highlighted("highlighted-nations").score(0.11480146).collateMatch(false))
.highlighted("highlighted-nations") .options(option -> option.text("national").highlighted("highlighted-national").score(0.08063514)
.score(0.11480146)
.collateMatch(false))
.options(option -> option
.text("national")
.highlighted("highlighted-national")
.score(0.08063514)
.collateMatch(false))) .collateMatch(false)))
.build(); .build();
final var sortProperties = ImmutableMap.<String, List<Suggestion<EntityAsMap>>> builder() final var sortProperties = ImmutableMap.<String, List<Suggestion<EntityAsMap>>> builder()
.put("suggestionTest", ImmutableList.of(suggestionTest)) .put("suggestionTest", ImmutableList.of(suggestionTest)).build();
.build();
// act // act
final var actual = SearchDocumentResponseBuilder.from(hitsMetadata, null, null, null, null, sortProperties, null, final var actual = SearchDocumentResponseBuilder.from(hitsMetadata, null, null, null, 0, null, sortProperties, null,
jsonpMapper); jsonpMapper);
// assert // assert
@ -122,35 +109,19 @@ class SearchDocumentResponseBuilderUnitTests {
void shouldGetShardStatisticsInfo() { void shouldGetShardStatisticsInfo() {
// arrange // arrange
HitsMetadata<EntityAsMap> hitsMetadata = new HitsMetadata.Builder<EntityAsMap>() HitsMetadata<EntityAsMap> hitsMetadata = new HitsMetadata.Builder<EntityAsMap>()
.total(t -> t .total(t -> t.value(0).relation(TotalHitsRelation.Eq)).hits(new ArrayList<>()).build();
.value(0)
.relation(TotalHitsRelation.Eq))
.hits(new ArrayList<>())
.build();
ShardStatistics shards = new ShardStatistics.Builder() ShardStatistics shards = new ShardStatistics.Builder().total(15).successful(14).skipped(0).failed(1)
.total(15) .failures(List.of(ShardFailure.of(sfb -> sfb.index("test-index").node("test-node").shard(1)
.successful(14) .reason(rb -> rb.reason("this is a mock failure in shards")
.skipped(0) .causedBy(cbb -> cbb.reason("inner reason").metadata(Map.of("hello", JsonData.of("world"))))
.failed(1)
.failures(List.of(
ShardFailure.of(sfb -> sfb
.index("test-index")
.node("test-node")
.shard(1)
.reason(rb -> rb
.reason("this is a mock failure in shards")
.causedBy(cbb -> cbb.reason("inner reason")
.metadata(Map.of("hello", JsonData.of("world"))))
.type("reason-type") .type("reason-type")
) ).status("fail")))).build();
.status("fail"))))
.build();
// act // act
SearchDocumentResponse response = SearchDocumentResponseBuilder.from(hitsMetadata, shards, null, null, SearchDocumentResponse response = SearchDocumentResponseBuilder.from(hitsMetadata, shards, null, null, 0, null,
null, null, null, jsonpMapper); null, null, jsonpMapper);
// assert // assert
SearchShardStatistics shardStatistics = response.getSearchShardStatistics(); SearchShardStatistics shardStatistics = response.getSearchShardStatistics();
@ -164,11 +135,9 @@ class SearchDocumentResponseBuilderUnitTests {
assertThat(failures.size()).isEqualTo(1); assertThat(failures.size()).isEqualTo(1);
assertThat(failures).extracting(SearchShardStatistics.Failure::getIndex).containsExactly("test-index"); assertThat(failures).extracting(SearchShardStatistics.Failure::getIndex).containsExactly("test-index");
assertThat(failures).extracting(SearchShardStatistics.Failure::getElasticsearchErrorCause) assertThat(failures).extracting(SearchShardStatistics.Failure::getElasticsearchErrorCause)
.extracting(ElasticsearchErrorCause::getReason) .extracting(ElasticsearchErrorCause::getReason).containsExactly("this is a mock failure in shards");
.containsExactly("this is a mock failure in shards");
assertThat(failures).extracting(SearchShardStatistics.Failure::getElasticsearchErrorCause) assertThat(failures).extracting(SearchShardStatistics.Failure::getElasticsearchErrorCause)
.extracting(ElasticsearchErrorCause::getCausedBy) .extracting(ElasticsearchErrorCause::getCausedBy).extracting(ElasticsearchErrorCause::getReason)
.extracting(ElasticsearchErrorCause::getReason)
.containsExactly("inner reason"); .containsExactly("inner reason");
} }
} }

View File

@ -24,6 +24,7 @@ import static org.springframework.data.elasticsearch.core.query.StringQuery.*;
import static org.springframework.data.elasticsearch.utils.IdGenerator.*; import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*; import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -99,6 +100,7 @@ import org.springframework.lang.Nullable;
* @author scoobyzhang * @author scoobyzhang
* @author Hamid Rahimi * @author Hamid Rahimi
* @author Illia Ulianov * @author Illia Ulianov
* @author Mohamed El Harrougui
*/ */
@SpringIntegrationTest @SpringIntegrationTest
public abstract class ElasticsearchIntegrationTests { public abstract class ElasticsearchIntegrationTests {
@ -1855,7 +1857,7 @@ public abstract class ElasticsearchIntegrationTests {
protected abstract Query getBoolQueryWithWildcardsFirstMustSecondShouldAndMinScore(String firstField, protected abstract Query getBoolQueryWithWildcardsFirstMustSecondShouldAndMinScore(String firstField,
String firstValue, String secondField, String secondValue, float minScore); String firstValue, String secondField, String secondValue, float minScore);
@Test // DATAES-462 @Test // DATAES-462, #2986
public void shouldReturnScores() { public void shouldReturnScores() {
List<IndexQuery> indexQueries = new ArrayList<>(); List<IndexQuery> indexQueries = new ArrayList<>();
@ -1872,6 +1874,7 @@ public abstract class ElasticsearchIntegrationTests {
IndexCoordinates.of(indexNameProvider.indexName())); IndexCoordinates.of(indexNameProvider.indexName()));
assertThat(searchHits.getMaxScore()).isGreaterThan(0f); assertThat(searchHits.getMaxScore()).isGreaterThan(0f);
assertThat(searchHits.getExecutionDuration().toMillis()).isGreaterThan(0);
assertThat(searchHits.getSearchHit(0).getScore()).isGreaterThan(0f); assertThat(searchHits.getSearchHit(0).getScore()).isGreaterThan(0f);
} }

View File

@ -19,6 +19,7 @@ import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
@ -33,6 +34,7 @@ import org.springframework.data.util.CloseableIterator;
* @author Roman Puchkovskiy * @author Roman Puchkovskiy
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
*/ */
class SearchHitSupportTest { class SearchHitSupportTest {
@ -65,8 +67,8 @@ class SearchHitSupportTest {
hits.add(new SearchHit<>(null, null, null, 0, null, null, null, null, null, null, "four")); hits.add(new SearchHit<>(null, null, null, 0, null, null, null, null, null, null, "four"));
hits.add(new SearchHit<>(null, null, null, 0, null, null, null, null, null, null, "five")); hits.add(new SearchHit<>(null, null, null, 0, null, null, null, null, null, null, "five"));
SearchHits<String> originalSearchHits = new SearchHitsImpl<>(hits.size(), TotalHitsRelation.EQUAL_TO, 0, "scroll", SearchHits<String> originalSearchHits = new SearchHitsImpl<>(hits.size(), TotalHitsRelation.EQUAL_TO, 0,
null, hits, null, null, null); Duration.ofMillis(1), "scroll", null, hits, null, null, null);
SearchPage<String> searchPage = SearchHitSupport.searchPageFor(originalSearchHits, PageRequest.of(0, 3)); SearchPage<String> searchPage = SearchHitSupport.searchPageFor(originalSearchHits, PageRequest.of(0, 3));
SearchHits<String> searchHits = searchPage.getSearchHits(); SearchHits<String> searchHits = searchPage.getSearchHits();
@ -89,6 +91,11 @@ class SearchHitSupportTest {
return 0; return 0;
} }
@Override
public Duration getExecutionDuration() {
return Duration.ofMillis(1);
}
@Override @Override
public long getTotalHits() { public long getTotalHits() {
return 2; return 2;

View File

@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -32,6 +33,7 @@ import org.springframework.data.util.StreamUtils;
* @author Sascha Woo * @author Sascha Woo
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Haibo Liu * @author Haibo Liu
* @author Mohamed El Harrougui
*/ */
public class StreamQueriesTest { public class StreamQueriesTest {
@ -181,6 +183,7 @@ public class StreamQueriesTest {
} }
private SearchScrollHits<String> newSearchScrollHits(List<SearchHit<String>> hits, String scrollId) { private SearchScrollHits<String> newSearchScrollHits(List<SearchHit<String>> hits, String scrollId) {
return new SearchHitsImpl<>(hits.size(), TotalHitsRelation.EQUAL_TO, 0, scrollId, null, hits, null, null, null); return new SearchHitsImpl<>(hits.size(), TotalHitsRelation.EQUAL_TO, 0, Duration.ofMillis(1), scrollId, null, hits,
null, null, null);
} }
} }