From 5c862e80bf6005f3708af450b1d282d56454cd02 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Tue, 31 Dec 2019 13:55:56 +0100 Subject: [PATCH] DATAES-722 - Return total count relation in the SearchHits object. Original PR: #369 --- .../data/elasticsearch/core/SearchHits.java | 47 ++++++++++++++----- .../MappingElasticsearchConverter.java | 5 +- .../core/document/SearchDocumentResponse.java | 30 ++++++++---- .../core/ElasticsearchTemplateTests.java | 5 +- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/SearchHits.java b/src/main/java/org/springframework/data/elasticsearch/core/SearchHits.java index 3591078b3..c5a2e4317 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/SearchHits.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/SearchHits.java @@ -39,38 +39,50 @@ public class SearchHits implements Streamable> { private final String scrollId; private final List> searchHits; private final Aggregations aggregations; + private final TotalHitsRelation totalHitsRelation; /** - * @param totalHits - * @param maxScore + * @param totalHits the number of total hits for the search + * @param totalHitsRelation the relation {@see TotalHitsRelation}, must not be {@literal null} + * @param maxScore the maximum score + * @param scrollId the scroll id if available * @param searchHits must not be {@literal null} - * @param aggregations + * @param aggregations the aggregations if available */ - public SearchHits(long totalHits, float maxScore, @Nullable String scrollId, List> searchHits, - @Nullable Aggregations aggregations) { + public SearchHits(long totalHits, TotalHitsRelation totalHitsRelation, float maxScore, @Nullable String scrollId, + List> searchHits, @Nullable Aggregations aggregations) { Assert.notNull(searchHits, "searchHits must not be null"); this.totalHits = totalHits; + this.totalHitsRelation = totalHitsRelation; this.maxScore = maxScore; this.scrollId = scrollId; this.searchHits = searchHits; this.aggregations = aggregations; } + @SuppressWarnings("unchecked") @Override public Iterator> iterator() { return (Iterator>) searchHits.iterator(); } + // region getter /** * @return the number of total hits. */ - // region getter public long getTotalHits() { return totalHits; } + /** + * @return the relation for the total hits + */ + public TotalHitsRelation getTotalHitsRelation() { + return totalHitsRelation; + } + /** * @return the maximum score */ @@ -107,19 +119,20 @@ public class SearchHits implements Streamable> { @Override public String toString() { - return "SearchHits{" + - "totalHits=" + totalHits + - ", maxScore=" + maxScore + - ", scrollId='" + scrollId + '\'' + - ", searchHits=" + StringUtils.collectionToCommaDelimitedString(searchHits) + - ", aggregations=" + aggregations + + return "SearchHits{" + // + "totalHits=" + totalHits + // + ", totalHitsRelation=" + totalHitsRelation + // + ", maxScore=" + maxScore + // + ", scrollId='" + scrollId + '\'' + // + ", searchHits={" + searchHits.size() + " elements}" + // + ", aggregations=" + aggregations + // '}'; } + // region aggregations /** * @return true if aggregations are available */ - // region aggregations public boolean hasAggregations() { return aggregations != null; } @@ -133,4 +146,12 @@ public class SearchHits implements Streamable> { } // endregion + /** + * Enum to represent the relation that Elasticsearch returns for the totalHits value {@see Ekasticsearch + * docs} + */ + public enum TotalHitsRelation { + EQUAL_TO, GREATER_THAN_OR_EQUAL_TO + } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java index 2664e0f5b..2b204e9a7 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java @@ -169,7 +169,10 @@ public class MappingElasticsearchConverter .map(searchDocument -> read(type, searchDocument)) // .collect(Collectors.toList()); Aggregations aggregations = searchDocumentResponse.getAggregations(); - return new SearchHits<>(totalHits, maxScore, scrollId, searchHits, aggregations); + SearchHits.TotalHitsRelation totalHitsRelation = SearchHits.TotalHitsRelation + .valueOf(searchDocumentResponse.getTotalHitsRelation()); + + return new SearchHits<>(totalHits, totalHitsRelation, maxScore, scrollId, searchHits, aggregations); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/document/SearchDocumentResponse.java b/src/main/java/org/springframework/data/elasticsearch/core/document/SearchDocumentResponse.java index fd1b0e714..89cf9ea74 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/document/SearchDocumentResponse.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/document/SearchDocumentResponse.java @@ -20,14 +20,14 @@ import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import org.apache.lucene.search.TotalHits; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.aggregations.Aggregations; -import org.springframework.data.elasticsearch.support.SearchHitsUtil; import org.springframework.util.Assert; /** * This represents the complete search response from Elasticsearch, including the returned documents. Instances must be - * created with the {@link #from(org.elasticsearch.action.search.SearchResponse)} method. + * created with the {@link #from(SearchResponse)} method. * * @author Peter-Josef Meisch * @since 4.0 @@ -35,14 +35,16 @@ import org.springframework.util.Assert; public class SearchDocumentResponse { private long totalHits; + private String totalHitsRelation; private float maxScore; private final String scrollId; private final List searchDocuments; private final Aggregations aggregations; - private SearchDocumentResponse(long totalHits, float maxScore, String scrollId, List searchDocuments, - Aggregations aggregations) { + private SearchDocumentResponse(long totalHits, String totalHitsRelation, float maxScore, String scrollId, + List searchDocuments, Aggregations aggregations) { this.totalHits = totalHits; + this.totalHitsRelation = totalHitsRelation; this.maxScore = maxScore; this.scrollId = scrollId; this.searchDocuments = searchDocuments; @@ -53,6 +55,10 @@ public class SearchDocumentResponse { return totalHits; } + public String getTotalHitsRelation() { + return totalHitsRelation; + } + public float getMaxScore() { return maxScore; } @@ -70,23 +76,29 @@ public class SearchDocumentResponse { } /** - * creates a SearchDocumentResponse from the {@link org.elasticsearch.action.search.SearchResponse} + * creates a SearchDocumentResponse from the {@link SearchResponse} * - * @param searchResponse must not be {@literal null} - * @return + * @param searchResponse + * must not be {@literal null} + * @return the SearchDocumentResponse */ public static SearchDocumentResponse from(SearchResponse searchResponse) { Assert.notNull(searchResponse, "searchResponse must not be null"); - long totalHits = SearchHitsUtil.getTotalCount(searchResponse.getHits()); + TotalHits responseTotalHits = searchResponse.getHits().getTotalHits(); + long totalHits = responseTotalHits.value; + String totalHitsRelation = responseTotalHits.relation.name(); + float maxScore = searchResponse.getHits().getMaxScore(); String scrollId = searchResponse.getScrollId(); + List searchDocuments = StreamSupport.stream(searchResponse.getHits().spliterator(), false) // .filter(Objects::nonNull) // .map(DocumentAdapters::from) // .collect(Collectors.toList()); + Aggregations aggregations = searchResponse.getAggregations(); - return new SearchDocumentResponse(totalHits, maxScore, scrollId, searchDocuments, aggregations); + return new SearchDocumentResponse(totalHits, totalHitsRelation, maxScore, scrollId, searchDocuments, aggregations); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index a6c276cdb..3b8205f94 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -192,7 +192,7 @@ public abstract class ElasticsearchTemplateTests { assertThat(count).isEqualTo(1); } - @Test + @Test // DATAES-722 public void shouldReturnObjectForGivenId() { // given @@ -289,7 +289,8 @@ public abstract class ElasticsearchTemplateTests { // then assertThat(searchHits).isNotNull(); - assertThat(searchHits.getTotalHits()).isGreaterThanOrEqualTo(1); + assertThat(searchHits.getTotalHits()).isEqualTo(1); + assertThat(searchHits.getTotalHitsRelation()).isEqualByComparingTo(SearchHits.TotalHitsRelation.EQUAL_TO); } @Test // DATAES-595