mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-30 16:52:11 +00:00
parent
ddc7246c42
commit
63eebdea88
@ -1144,6 +1144,8 @@ class RequestFactory {
|
||||
sourceBuilder.timeout(timeout);
|
||||
}
|
||||
|
||||
sourceBuilder.explain(query.getExplain());
|
||||
|
||||
request.source(sourceBuilder);
|
||||
return request;
|
||||
}
|
||||
@ -1224,6 +1226,8 @@ class RequestFactory {
|
||||
searchRequestBuilder.setTimeout(timeout);
|
||||
}
|
||||
|
||||
searchRequestBuilder.setExplain(query.getExplain());
|
||||
|
||||
return searchRequestBuilder;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@ -44,16 +45,18 @@ public class SearchHit<T> {
|
||||
private final Map<String, List<String>> highlightFields = new LinkedHashMap<>();
|
||||
private final Map<String, SearchHits<?>> innerHits = new LinkedHashMap<>();
|
||||
@Nullable private final NestedMetaData nestedMetaData;
|
||||
@Nullable private String routing;
|
||||
@Nullable private final String routing;
|
||||
@Nullable private final Explanation explanation;
|
||||
|
||||
public SearchHit(@Nullable String index, @Nullable String id, @Nullable String routing, float score,
|
||||
@Nullable Object[] sortValues, @Nullable Map<String, List<String>> highlightFields, T content) {
|
||||
this(index, id, routing, score, sortValues, highlightFields, null, null, content);
|
||||
this(index, id, routing, score, sortValues, highlightFields, null, null, null, content);
|
||||
}
|
||||
|
||||
public SearchHit(@Nullable String index, @Nullable String id, @Nullable String routing, float score,
|
||||
@Nullable Object[] sortValues, @Nullable Map<String, List<String>> highlightFields,
|
||||
@Nullable Map<String, SearchHits<?>> innerHits, @Nullable NestedMetaData nestedMetaData, T content) {
|
||||
@Nullable Map<String, SearchHits<?>> innerHits, @Nullable NestedMetaData nestedMetaData,
|
||||
@Nullable Explanation explanation, T content) {
|
||||
this.index = index;
|
||||
this.id = id;
|
||||
this.routing = routing;
|
||||
@ -69,7 +72,7 @@ public class SearchHit<T> {
|
||||
}
|
||||
|
||||
this.nestedMetaData = nestedMetaData;
|
||||
|
||||
this.explanation = explanation;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@ -176,4 +179,13 @@ public class SearchHit<T> {
|
||||
public String getRouting() {
|
||||
return routing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the explanation for this SearchHit.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nullable
|
||||
public Explanation getExplanation() {
|
||||
return explanation;
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ class SearchHitMapping<T> {
|
||||
getHighlightsAndRemapFieldNames(searchDocument), //
|
||||
mapInnerHits(searchDocument), //
|
||||
searchDocument.getNestedMetaData(), //
|
||||
searchDocument.getExplanation(), //
|
||||
content); //
|
||||
}
|
||||
|
||||
@ -196,6 +197,7 @@ class SearchHitMapping<T> {
|
||||
searchDocument.getHighlightFields(), //
|
||||
searchHit.getInnerHits(), //
|
||||
persistentEntityWithNestedMetaData.nestedMetaData, //
|
||||
searchHit.getExplanation(), //
|
||||
targetObject));
|
||||
});
|
||||
|
||||
|
@ -161,16 +161,12 @@ public class DocumentAdapters {
|
||||
Map<String, SearchHits> sourceInnerHits = source.getInnerHits();
|
||||
|
||||
if (sourceInnerHits != null) {
|
||||
sourceInnerHits.forEach((name, searchHits) -> {
|
||||
innerHits.put(name, SearchDocumentResponse.from(searchHits, null, null));
|
||||
});
|
||||
sourceInnerHits
|
||||
.forEach((name, searchHits) -> innerHits.put(name, SearchDocumentResponse.from(searchHits, null, null)));
|
||||
}
|
||||
|
||||
NestedMetaData nestedMetaData = null;
|
||||
|
||||
if (source.getNestedIdentity() != null) {
|
||||
nestedMetaData = from(source.getNestedIdentity());
|
||||
}
|
||||
NestedMetaData nestedMetaData = from(source.getNestedIdentity());
|
||||
Explanation explanation = from(source.getExplanation());
|
||||
|
||||
BytesReference sourceRef = source.getSourceRef();
|
||||
|
||||
@ -178,7 +174,7 @@ public class DocumentAdapters {
|
||||
return new SearchDocumentAdapter(
|
||||
source.getScore(), source.getSortValues(), source.getFields(), highlightFields, fromDocumentFields(source,
|
||||
source.getIndex(), source.getId(), source.getVersion(), source.getSeqNo(), source.getPrimaryTerm()),
|
||||
innerHits, nestedMetaData);
|
||||
innerHits, nestedMetaData, explanation);
|
||||
}
|
||||
|
||||
Document document = Document.from(source.getSourceAsMap());
|
||||
@ -192,17 +188,32 @@ public class DocumentAdapters {
|
||||
document.setPrimaryTerm(source.getPrimaryTerm());
|
||||
|
||||
return new SearchDocumentAdapter(source.getScore(), source.getSortValues(), source.getFields(), highlightFields,
|
||||
document, innerHits, nestedMetaData);
|
||||
document, innerHits, nestedMetaData, explanation);
|
||||
}
|
||||
|
||||
private static NestedMetaData from(SearchHit.NestedIdentity nestedIdentity) {
|
||||
@Nullable
|
||||
private static Explanation from(@Nullable org.apache.lucene.search.Explanation explanation) {
|
||||
|
||||
NestedMetaData child = null;
|
||||
|
||||
if (nestedIdentity.getChild() != null) {
|
||||
child = from(nestedIdentity.getChild());
|
||||
if (explanation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Explanation> details = new ArrayList<>();
|
||||
for (org.apache.lucene.search.Explanation detail : explanation.getDetails()) {
|
||||
details.add(from(detail));
|
||||
}
|
||||
|
||||
return new Explanation(explanation.isMatch(), explanation.getValue().doubleValue(), explanation.getDescription(),
|
||||
details);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static NestedMetaData from(@Nullable SearchHit.NestedIdentity nestedIdentity) {
|
||||
|
||||
if (nestedIdentity == null) {
|
||||
return null;
|
||||
}
|
||||
NestedMetaData child = from(nestedIdentity.getChild());
|
||||
return NestedMetaData.of(nestedIdentity.getField().string(), nestedIdentity.getOffset(), child);
|
||||
}
|
||||
|
||||
@ -210,7 +221,7 @@ public class DocumentAdapters {
|
||||
* Create an unmodifiable {@link Document} from {@link Iterable} of {@link DocumentField}s.
|
||||
*
|
||||
* @param documentFields the {@link DocumentField}s backing the {@link Document}.
|
||||
* @param index
|
||||
* @param index the index where the Document was found
|
||||
* @return the adapted {@link Document}.
|
||||
*/
|
||||
public static Document fromDocumentFields(Iterable<DocumentField> documentFields, String index, String id,
|
||||
@ -458,10 +469,11 @@ public class DocumentAdapters {
|
||||
private final Map<String, List<String>> highlightFields = new HashMap<>();
|
||||
private final Map<String, SearchDocumentResponse> innerHits = new HashMap<>();
|
||||
@Nullable private final NestedMetaData nestedMetaData;
|
||||
@Nullable private final Explanation explanation;
|
||||
|
||||
SearchDocumentAdapter(float score, Object[] sortValues, Map<String, DocumentField> fields,
|
||||
Map<String, List<String>> highlightFields, Document delegate, Map<String, SearchDocumentResponse> innerHits,
|
||||
@Nullable NestedMetaData nestedMetaData) {
|
||||
@Nullable NestedMetaData nestedMetaData, @Nullable Explanation explanation) {
|
||||
|
||||
this.score = score;
|
||||
this.sortValues = sortValues;
|
||||
@ -470,6 +482,7 @@ public class DocumentAdapters {
|
||||
this.highlightFields.putAll(highlightFields);
|
||||
this.innerHits.putAll(innerHits);
|
||||
this.nestedMetaData = nestedMetaData;
|
||||
this.explanation = explanation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -646,6 +659,12 @@ public class DocumentAdapters {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Explanation getExplanation() {
|
||||
return explanation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.document;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* class that holds explanations returned from an Elasticsearch search.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class Explanation {
|
||||
private final boolean match;
|
||||
private final Double value;
|
||||
@Nullable private final String description;
|
||||
private final List<Explanation> details;
|
||||
|
||||
public Explanation(boolean match, Double value, @Nullable String description, List<Explanation> details) {
|
||||
|
||||
Assert.notNull(value, "value must not be null");
|
||||
Assert.notNull(details, "details must not be null");
|
||||
|
||||
this.match = match;
|
||||
this.value = value;
|
||||
this.description = description;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public boolean isMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<Explanation> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Explanation that = (Explanation) o;
|
||||
|
||||
if (match != that.match)
|
||||
return false;
|
||||
if (!value.equals(that.value))
|
||||
return false;
|
||||
if (!Objects.equals(description, that.description))
|
||||
return false;
|
||||
return details.equals(that.details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (match ? 1 : 0);
|
||||
result = 31 * result + value.hashCode();
|
||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||
result = 31 * result + details.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Explanation{" + //
|
||||
"match=" + match + //
|
||||
", value=" + value + //
|
||||
", description='" + description + '\'' + //
|
||||
", details=" + details + //
|
||||
'}'; //
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ import java.util.Map;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Extension to {@link Document} exposing a search response related data.
|
||||
* Extension to {@link Document} exposing search response related data.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Peter-Josef Meisch
|
||||
@ -98,4 +98,11 @@ public interface SearchDocument extends Document {
|
||||
default String getRouting() {
|
||||
return getFieldValue("_routing");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the explanation for the SearchHit.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nullable
|
||||
Explanation getExplanation();
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Classes related to the Document structure of Elasticsearch documents and search responses.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
@org.springframework.lang.NonNullFields
|
||||
package org.springframework.data.elasticsearch.core.document;
|
||||
|
@ -61,6 +61,7 @@ abstract class AbstractQuery implements Query {
|
||||
@Nullable private Integer trackTotalHitsUpTo;
|
||||
@Nullable private Duration scrollTime;
|
||||
@Nullable private TimeValue timeout;
|
||||
private boolean explain = false;
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@ -270,4 +271,16 @@ abstract class AbstractQuery implements Query {
|
||||
public void setTimeout(@Nullable TimeValue timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getExplain() {
|
||||
return explain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param explain the explain flag on the query.
|
||||
*/
|
||||
public void setExplain(boolean explain) {
|
||||
this.explain = explain;
|
||||
}
|
||||
}
|
||||
|
@ -285,4 +285,12 @@ public interface Query {
|
||||
*/
|
||||
@Nullable
|
||||
TimeValue getTimeout();
|
||||
|
||||
/**
|
||||
* @return {@literal true} when the query has the eplain parameter set, defaults to {@literal false}
|
||||
* @since 4.2
|
||||
*/
|
||||
default boolean getExplain() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
@ -31,9 +32,11 @@ import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
|
||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||
import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||
|
||||
/**
|
||||
@ -236,4 +239,27 @@ public class DocumentAdaptersUnitTests {
|
||||
assertThat(document.hasPrimaryTerm()).isTrue();
|
||||
assertThat(document.getPrimaryTerm()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // #725
|
||||
@DisplayName("should adapt returned explanations")
|
||||
void shouldAdaptReturnedExplanations() {
|
||||
|
||||
SearchHit searchHit = new SearchHit(42);
|
||||
searchHit.explanation(org.apache.lucene.search.Explanation.match( //
|
||||
3.14, //
|
||||
"explanation 3.14", //
|
||||
Collections.singletonList(org.apache.lucene.search.Explanation.noMatch( //
|
||||
"explanation noMatch", //
|
||||
Collections.emptyList()))));
|
||||
|
||||
SearchDocument searchDocument = DocumentAdapters.from(searchHit);
|
||||
|
||||
Explanation explanation = searchDocument.getExplanation();
|
||||
assertThat(explanation).isNotNull();
|
||||
assertThat(explanation.isMatch()).isTrue();
|
||||
assertThat(explanation.getValue()).isEqualTo(3.14);
|
||||
assertThat(explanation.getDescription()).isEqualTo("explanation 3.14");
|
||||
List<Explanation> details = explanation.getDetails();
|
||||
assertThat(details).containsExactly(new Explanation(false, 0.0, "explanation noMatch", Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,16 @@ import java.lang.Double;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Long;
|
||||
import java.lang.Object;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
@ -74,6 +83,7 @@ import org.springframework.data.elasticsearch.annotations.JoinTypeRelation;
|
||||
import org.springframework.data.elasticsearch.annotations.JoinTypeRelations;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.data.elasticsearch.core.index.AliasAction;
|
||||
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
|
||||
@ -124,7 +134,6 @@ public abstract class ElasticsearchTemplateTests {
|
||||
@Autowired protected ElasticsearchOperations operations;
|
||||
protected IndexOperations indexOperations;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
indexOperations = operations.indexOps(SampleEntity.class);
|
||||
@ -1546,10 +1555,8 @@ public abstract class ElasticsearchTemplateTests {
|
||||
|
||||
final UpdateQuery updateQuery = UpdateQuery.builder(query)
|
||||
.withScriptType(org.springframework.data.elasticsearch.core.ScriptType.INLINE)
|
||||
.withScript("ctx._source['message'] = params['newMessage']")
|
||||
.withLang("painless")
|
||||
.withParams(Collections.singletonMap("newMessage", messageAfterUpdate))
|
||||
.withAbortOnVersionConflict(true)
|
||||
.withScript("ctx._source['message'] = params['newMessage']").withLang("painless")
|
||||
.withParams(Collections.singletonMap("newMessage", messageAfterUpdate)).withAbortOnVersionConflict(true)
|
||||
.build();
|
||||
|
||||
// when
|
||||
@ -3619,7 +3626,7 @@ public abstract class ElasticsearchTemplateTests {
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // DATAES-907
|
||||
@DisplayName("should track total hits is off")
|
||||
void shouldTrackTotalHitsIsOff() {
|
||||
|
||||
@ -3642,6 +3649,39 @@ public abstract class ElasticsearchTemplateTests {
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
@Test // #725
|
||||
@DisplayName("should not return explanation when not requested")
|
||||
void shouldNotReturnExplanationWhenNotRequested() {
|
||||
|
||||
SampleEntity entity = SampleEntity.builder().id("42").message("a message with text").build();
|
||||
operations.save(entity);
|
||||
Criteria criteria = new Criteria("message").contains("with");
|
||||
CriteriaQuery query = new CriteriaQuery(criteria);
|
||||
|
||||
SearchHits<SampleEntity> searchHits = operations.search(query, SampleEntity.class);
|
||||
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1L);
|
||||
Explanation explanation = searchHits.getSearchHit(0).getExplanation();
|
||||
assertThat(explanation).isNull();
|
||||
}
|
||||
|
||||
@Test // #725
|
||||
@DisplayName("should return explanation when requested")
|
||||
void shouldReturnExplanationWhenRequested() {
|
||||
|
||||
SampleEntity entity = SampleEntity.builder().id("42").message("a message with text").build();
|
||||
operations.save(entity);
|
||||
Criteria criteria = new Criteria("message").contains("with");
|
||||
CriteriaQuery query = new CriteriaQuery(criteria);
|
||||
query.setExplain(true);
|
||||
|
||||
SearchHits<SampleEntity> searchHits = operations.search(query, SampleEntity.class);
|
||||
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1L);
|
||||
Explanation explanation = searchHits.getSearchHit(0).getExplanation();
|
||||
assertThat(explanation).isNotNull();
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ -3836,5 +3876,4 @@ public abstract class ElasticsearchTemplateTests {
|
||||
@JoinTypeRelation(parent = "question", children = { "answer" }) }) private JoinField<String> myJoinField;
|
||||
@Field(type = Text) private String text;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.elasticsearch.core.document.Explanation;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
@ -1058,6 +1059,45 @@ public class ReactiveElasticsearchTemplateIntegrationTests {
|
||||
.expectNext(true) //
|
||||
.verifyComplete(); //
|
||||
}
|
||||
|
||||
@Test // #725
|
||||
@DisplayName("should not return explanation when not requested")
|
||||
void shouldNotReturnExplanationWhenNotRequested() {
|
||||
|
||||
ElasticsearchTemplateTests.SampleEntity entity = ElasticsearchTemplateTests.SampleEntity.builder().id("42").message("a message with text").build();
|
||||
template.save(entity).as(StepVerifier::create).expectNextCount(1).verifyComplete();
|
||||
|
||||
Criteria criteria = new Criteria("message").contains("with");
|
||||
CriteriaQuery query = new CriteriaQuery(criteria);
|
||||
|
||||
template.search(query, ElasticsearchTemplateTests.SampleEntity.class)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(searchHit -> {
|
||||
Explanation explanation = searchHit.getExplanation();
|
||||
assertThat(explanation).isNull();
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #725
|
||||
@DisplayName("should return explanation when requested")
|
||||
void shouldReturnExplanationWhenRequested() {
|
||||
|
||||
ElasticsearchTemplateTests.SampleEntity entity = ElasticsearchTemplateTests.SampleEntity.builder().id("42").message("a message with text").build();
|
||||
template.save(entity).as(StepVerifier::create).expectNextCount(1).verifyComplete();
|
||||
|
||||
Criteria criteria = new Criteria("message").contains("with");
|
||||
CriteriaQuery query = new CriteriaQuery(criteria);
|
||||
query.setExplain(true);
|
||||
|
||||
template.search(query, ElasticsearchTemplateTests.SampleEntity.class)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(searchHit -> {
|
||||
Explanation explanation = searchHit.getExplanation();
|
||||
assertThat(explanation).isNotNull();
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Helper functions
|
||||
|
Loading…
x
Reference in New Issue
Block a user