mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-13 23:52:10 +00:00
Refactoring to prepare for removal of the old deprecated RestHighLevelClient integration.
Original Pull Request #2559 Closes #2557
This commit is contained in:
parent
f897dd4318
commit
73e9a6f5c5
@ -9,7 +9,7 @@
|
||||
[[new-features.5-1-0]]
|
||||
== New in Spring Data Elasticsearch 5.1
|
||||
|
||||
* Upgrade to Elasticsearch 8.7.0
|
||||
* Upgrade to Elasticsearch 8.7.1
|
||||
* Allow specification of the TLS certificate when connecting to an Elasticsearch 8 cluster
|
||||
|
||||
[[new-features.5-0-0]]
|
||||
|
@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.ReactiveElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.cluster.ReactiveClusterOperations;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
@ -28,11 +27,6 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of Elasticsearch operations executed in a reactive way.
|
||||
* <p>
|
||||
* Implemented by {@link ReactiveElasticsearchTemplate}. Not often used but a useful option for extensibility and
|
||||
* testability (as it can be easily mocked, stubbed, or be the target of a JDK proxy). Command execution using
|
||||
* {@link ReactiveElasticsearchOperations} is deferred until a {@link org.reactivestreams.Subscriber} subscribes to the
|
||||
* {@link Publisher}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2023 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;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.elasticsearch.action.bulk.BulkItemResponse;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.get.MultiGetItemResponse;
|
||||
import org.elasticsearch.action.get.MultiGetRequest;
|
||||
import org.elasticsearch.action.get.MultiGetResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.search.MultiSearchRequest;
|
||||
import org.elasticsearch.action.search.MultiSearchResponse;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.ElasticsearchRestTemplate;
|
||||
|
||||
/**
|
||||
* @author Roman Puchkovskiy
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class ElasticsearchRestTemplateCallbackTests extends ElasticsearchTemplateCallbackTests {
|
||||
|
||||
@Mock private RestHighLevelClient client;
|
||||
|
||||
@Mock private IndexResponse indexResponse;
|
||||
@Mock private BulkResponse bulkResponse;
|
||||
@Mock private BulkItemResponse bulkItemResponse;
|
||||
@Mock private GetResponse getResponse;
|
||||
@Mock private MultiGetResponse multiGetResponse;
|
||||
@Mock private MultiGetItemResponse multiGetItemResponse;
|
||||
@Mock private MultiSearchResponse.Item multiSearchResponseItem;
|
||||
|
||||
@SuppressWarnings("deprecation") // we know what we test
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
initTemplate(new ElasticsearchRestTemplate(client));
|
||||
|
||||
doReturn(indexResponse).when(client).index(any(IndexRequest.class), any(RequestOptions.class));
|
||||
doReturn("response-id").when(indexResponse).getId();
|
||||
|
||||
doReturn(bulkResponse).when(client).bulk(any(BulkRequest.class), any(RequestOptions.class));
|
||||
doReturn(new BulkItemResponse[] { bulkItemResponse, bulkItemResponse }).when(bulkResponse).getItems();
|
||||
doReturn("response-id").when(bulkItemResponse).getId();
|
||||
|
||||
doReturn(getResponse).when(client).get(any(GetRequest.class), any(RequestOptions.class));
|
||||
|
||||
doReturn(true).when(getResponse).isExists();
|
||||
doReturn(false).when(getResponse).isSourceEmpty();
|
||||
doReturn(new HashMap<String, Object>() {
|
||||
{
|
||||
put("id", "init");
|
||||
put("firstname", "luke");
|
||||
}
|
||||
}).when(getResponse).getSourceAsMap();
|
||||
|
||||
doReturn(multiGetResponse).when(client).mget(any(MultiGetRequest.class), any(RequestOptions.class));
|
||||
doReturn(new MultiGetItemResponse[] { multiGetItemResponse, multiGetItemResponse }).when(multiGetResponse)
|
||||
.getResponses();
|
||||
doReturn(getResponse).when(multiGetItemResponse).getResponse();
|
||||
|
||||
doReturn(searchResponse).when(client).search(any(SearchRequest.class), any(RequestOptions.class));
|
||||
doReturn(nSearchHits(2)).when(searchResponse).getHits();
|
||||
doReturn("scroll-id").when(searchResponse).getScrollId();
|
||||
doReturn(new BytesArray(new byte[8])).when(searchHit).getSourceRef();
|
||||
doReturn(new HashMap<String, Object>() {
|
||||
{
|
||||
put("id", "init");
|
||||
put("firstname", "luke");
|
||||
}
|
||||
}).when(searchHit).getSourceAsMap();
|
||||
|
||||
MultiSearchResponse multiSearchResponse = new MultiSearchResponse(
|
||||
new MultiSearchResponse.Item[] { multiSearchResponseItem }, 1L);
|
||||
doReturn(multiSearchResponse).when(client).multiSearch(any(MultiSearchRequest.class), any());
|
||||
doReturn(multiSearchResponse).when(client).msearch(any(MultiSearchRequest.class), any());
|
||||
doReturn(searchResponse).when(multiSearchResponseItem).getResponse();
|
||||
|
||||
doReturn(searchResponse).when(client).scroll(any(SearchScrollRequest.class), any(RequestOptions.class));
|
||||
}
|
||||
}
|
@ -1,561 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2023 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;
|
||||
|
||||
import static java.util.Collections.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.lucene.search.TotalHits;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.event.AfterConvertCallback;
|
||||
import org.springframework.data.elasticsearch.core.event.AfterSaveCallback;
|
||||
import org.springframework.data.elasticsearch.core.event.BeforeConvertCallback;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.BulkOptions;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Roman Puchkovskiy
|
||||
*/
|
||||
abstract class ElasticsearchTemplateCallbackTests {
|
||||
|
||||
protected AbstractElasticsearchTemplate template;
|
||||
|
||||
@Mock protected SearchResponse searchResponse;
|
||||
@Mock protected org.elasticsearch.search.SearchHit searchHit;
|
||||
|
||||
private final IndexCoordinates index = IndexCoordinates.of("index");
|
||||
|
||||
@Spy private ValueCapturingAfterSaveCallback afterSaveCallback = new ValueCapturingAfterSaveCallback();
|
||||
@Spy private ValueCapturingAfterConvertCallback afterConvertCallback = new ValueCapturingAfterConvertCallback();
|
||||
@Spy private ValueCapturingBeforeConvertCallback beforeConvertCallback = new ValueCapturingBeforeConvertCallback();
|
||||
|
||||
protected final void initTemplate(AbstractElasticsearchTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
protected final org.elasticsearch.search.SearchHits nSearchHits(int count) {
|
||||
org.elasticsearch.search.SearchHit[] hits = new org.elasticsearch.search.SearchHit[count];
|
||||
Arrays.fill(hits, searchHit);
|
||||
return new org.elasticsearch.search.SearchHits(hits, new TotalHits(count, TotalHits.Relation.EQUAL_TO), 1.0f);
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void saveOneShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity = new Person("init", "luke");
|
||||
|
||||
Person saved = template.save(entity);
|
||||
|
||||
verify(afterSaveCallback).onAfterSave(eq(entity), any());
|
||||
assertThat(saved.firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void saveWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity = new Person("init", "luke");
|
||||
|
||||
Person saved = template.save(entity, index);
|
||||
|
||||
verify(afterSaveCallback).onAfterSave(eq(entity), eq(index));
|
||||
assertThat(saved.firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void saveArrayShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
Iterable<Person> saved = template.save(entity1, entity2);
|
||||
|
||||
verify(afterSaveCallback, times(2)).onAfterSave(any(), any());
|
||||
Iterator<Person> savedIterator = saved.iterator();
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void saveIterableShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
Iterable<Person> saved = template.save(Arrays.asList(entity1, entity2));
|
||||
|
||||
verify(afterSaveCallback, times(2)).onAfterSave(any(), any());
|
||||
Iterator<Person> savedIterator = saved.iterator();
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void saveIterableWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
Iterable<Person> saved = template.save(Arrays.asList(entity1, entity2), index);
|
||||
|
||||
verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index));
|
||||
Iterator<Person> savedIterator = saved.iterator();
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
assertThat(savedIterator.next().firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void indexShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity = new Person("init", "luke");
|
||||
|
||||
IndexQuery indexQuery = indexQueryForEntity(entity);
|
||||
template.index(indexQuery, index);
|
||||
|
||||
verify(afterSaveCallback).onAfterSave(eq(entity), eq(index));
|
||||
Person savedPerson = (Person) indexQuery.getObject();
|
||||
assertThat(savedPerson.firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
private IndexQuery indexQueryForEntity(Person entity) {
|
||||
IndexQuery indexQuery = new IndexQuery();
|
||||
indexQuery.setObject(entity);
|
||||
return indexQuery;
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void bulkIndexShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
IndexQuery query1 = indexQueryForEntity(entity1);
|
||||
IndexQuery query2 = indexQueryForEntity(entity2);
|
||||
template.bulkIndex(Arrays.asList(query1, query2), index);
|
||||
|
||||
verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index));
|
||||
Person savedPerson1 = (Person) query1.getObject();
|
||||
Person savedPerson2 = (Person) query2.getObject();
|
||||
assertThat(savedPerson1.firstname).isEqualTo("after-save");
|
||||
assertThat(savedPerson2.firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-771
|
||||
void bulkIndexWithOptionsShouldInvokeAfterSaveCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
IndexQuery query1 = indexQueryForEntity(entity1);
|
||||
IndexQuery query2 = indexQueryForEntity(entity2);
|
||||
template.bulkIndex(Arrays.asList(query1, query2), BulkOptions.defaultOptions(), index);
|
||||
|
||||
verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index));
|
||||
Person savedPerson1 = (Person) query1.getObject();
|
||||
Person savedPerson2 = (Person) query2.getObject();
|
||||
assertThat(savedPerson1.firstname).isEqualTo("after-save");
|
||||
assertThat(savedPerson2.firstname).isEqualTo("after-save");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void getShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
Person result = template.get("init", Person.class);
|
||||
|
||||
verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any());
|
||||
assertThat(result.firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
private Document lukeDocument() {
|
||||
return Document.create().append("id", "init").append("firstname", "luke");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void getWithCoordinatesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
Person result = template.get("init", Person.class, index);
|
||||
|
||||
verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index));
|
||||
assertThat(result.firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772, #1678
|
||||
void multiGetShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
List<MultiGetItem<Person>> results = template.multiGet(queryForTwo(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
assertThat(results.get(0).getItem().firstname).isEqualTo("after-convert");
|
||||
assertThat(results.get(1).getItem().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
private Query queryForTwo() {
|
||||
return new NativeSearchQueryBuilder().withIds(Arrays.asList("init1", "init2")).build();
|
||||
}
|
||||
|
||||
private Query queryForOne() {
|
||||
return new NativeSearchQueryBuilder().withIds(singletonList("init")).build();
|
||||
}
|
||||
|
||||
private void skipItemsFromScrollStart(CloseableIterator<Person> results) {
|
||||
results.next();
|
||||
results.next();
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void moreLikeThisShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHits<Person> results = template.search(moreLikeThisQuery(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
assertThat(results.getSearchHit(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(results.getSearchHit(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
private MoreLikeThisQuery moreLikeThisQuery() {
|
||||
MoreLikeThisQuery query = new MoreLikeThisQuery();
|
||||
query.setId("init");
|
||||
query.addFields("id");
|
||||
return query;
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchOneShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
doReturn(nSearchHits(1)).when(searchResponse).getHits();
|
||||
|
||||
SearchHit<Person> result = template.searchOne(queryForOne(), Person.class);
|
||||
|
||||
verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any());
|
||||
assertThat(result.getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchOneWithIndexCoordinatesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
doReturn(nSearchHits(1)).when(searchResponse).getHits();
|
||||
|
||||
SearchHit<Person> result = template.searchOne(queryForOne(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index));
|
||||
assertThat(result.getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void multiSearchShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
List<SearchHits<Person>> results = template.multiSearch(singletonList(queryForTwo()), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
List<SearchHit<Person>> hits = results.get(0).getSearchHits();
|
||||
assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void multiSearchWithMultipleEntityClassesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
List<SearchHits<?>> results = template.multiSearch(singletonList(queryForTwo()), singletonList(Person.class),
|
||||
index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
List<? extends SearchHit<?>> hits = results.get(0).getSearchHits();
|
||||
assertThat(((Person) hits.get(0).getContent()).firstname).isEqualTo("after-convert");
|
||||
assertThat(((Person) hits.get(1).getContent()).firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHits<Person> results = template.search(queryForTwo(), Person.class);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any());
|
||||
List<SearchHit<Person>> hits = results.getSearchHits();
|
||||
assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchWithIndexCoordinatesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHits<Person> results = template.search(queryForTwo(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
List<SearchHit<Person>> hits = results.getSearchHits();
|
||||
assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchViaMoreLikeThisShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHits<Person> results = template.search(moreLikeThisQuery(), Person.class);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any());
|
||||
List<SearchHit<Person>> hits = results.getSearchHits();
|
||||
assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchViaMoreLikeThisWithIndexCoordinatesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHits<Person> results = template.search(moreLikeThisQuery(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
List<SearchHit<Person>> hits = results.getSearchHits();
|
||||
assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchForStreamShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHitsIterator<Person> results = template.searchForStream(queryForTwo(), Person.class);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any());
|
||||
assertThat(results.next().getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(results.next().getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-772
|
||||
void searchForStreamWithIndexCoordinatesShouldInvokeAfterConvertCallback() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback));
|
||||
|
||||
SearchHitsIterator<Person> results = template.searchForStream(queryForTwo(), Person.class, index);
|
||||
|
||||
verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()),
|
||||
eq(index));
|
||||
assertThat(results.next().getContent().firstname).isEqualTo("after-convert");
|
||||
assertThat(results.next().getContent().firstname).isEqualTo("after-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-785
|
||||
void saveOneShouldInvokeBeforeConvertCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(beforeConvertCallback));
|
||||
|
||||
Person entity = new Person("init1", "luke1");
|
||||
|
||||
Person saved = template.save(entity, index);
|
||||
|
||||
verify(beforeConvertCallback).onBeforeConvert(any(), eq(index));
|
||||
assertThat(saved.firstname).isEqualTo("before-convert");
|
||||
}
|
||||
|
||||
@Test // DATAES-785
|
||||
void saveAllShouldInvokeBeforeConvertCallbacks() {
|
||||
|
||||
template.setEntityCallbacks(EntityCallbacks.create(beforeConvertCallback));
|
||||
|
||||
Person entity1 = new Person("init1", "luke1");
|
||||
Person entity2 = new Person("init2", "luke2");
|
||||
|
||||
Iterable<Person> saved = template.save(Arrays.asList(entity1, entity2), index);
|
||||
|
||||
verify(beforeConvertCallback, times(2)).onBeforeConvert(any(), eq(index));
|
||||
Iterator<Person> iterator = saved.iterator();
|
||||
assertThat(iterator.next().firstname).isEqualTo("before-convert");
|
||||
assertThat(iterator.next().firstname).isEqualTo("before-convert");
|
||||
}
|
||||
|
||||
static class Person {
|
||||
@Nullable
|
||||
@Id String id;
|
||||
@Nullable String firstname;
|
||||
|
||||
public Person(@Nullable String id, @Nullable String firstname) {
|
||||
this.id = id;
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public Person() {}
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(@Nullable String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Person person = (Person) o;
|
||||
|
||||
if (!Objects.equals(id, person.id))
|
||||
return false;
|
||||
return Objects.equals(firstname, person.firstname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static class ValueCapturingEntityCallback<T> {
|
||||
|
||||
private final List<T> values = new ArrayList<>(1);
|
||||
|
||||
protected void capture(T value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
public List<T> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getValue() {
|
||||
return CollectionUtils.lastElement(values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ValueCapturingAfterSaveCallback extends ValueCapturingEntityCallback<Person>
|
||||
implements AfterSaveCallback<Person> {
|
||||
|
||||
@Override
|
||||
public Person onAfterSave(Person entity, IndexCoordinates index) {
|
||||
|
||||
capture(entity);
|
||||
return new Person() {
|
||||
{
|
||||
id = entity.id;
|
||||
firstname = "after-save";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCallback<Person>
|
||||
implements AfterConvertCallback<Person> {
|
||||
|
||||
@Override
|
||||
public Person onAfterConvert(Person entity, Document document, IndexCoordinates indexCoordinates) {
|
||||
|
||||
capture(entity);
|
||||
return new Person() {
|
||||
{
|
||||
id = entity.id;
|
||||
firstname = "after-convert";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static class ValueCapturingBeforeConvertCallback extends ValueCapturingEntityCallback<Person>
|
||||
implements BeforeConvertCallback<Person> {
|
||||
|
||||
@Override
|
||||
public Person onBeforeConvert(Person entity, IndexCoordinates indexCoordinates) {
|
||||
|
||||
capture(entity);
|
||||
return new Person() {
|
||||
{
|
||||
id = entity.id;
|
||||
firstname = "before-convert";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2023 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.suggest;
|
||||
|
||||
import co.elastic.clients.elasticsearch.core.search.CompletionContext;
|
||||
import co.elastic.clients.elasticsearch.core.search.FieldSuggester;
|
||||
import co.elastic.clients.elasticsearch.core.search.SuggestFuzziness;
|
||||
import co.elastic.clients.elasticsearch.core.search.Suggester;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.1
|
||||
*/
|
||||
@ContextConfiguration(classes = { CompletionWithContextsELCIntegrationTests.Config.class })
|
||||
public class CompletionWithContextsELCIntegrationTests extends CompletionWithContextsIntegrationTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchTemplateConfiguration.class })
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("completion-context");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getSearchQuery(String suggestionName, String category) {
|
||||
return NativeQuery.builder() //
|
||||
.withSuggester(Suggester.of(s -> s //
|
||||
.suggesters(//
|
||||
suggestionName, //
|
||||
FieldSuggester.of(fs -> fs //
|
||||
.prefix("m") //
|
||||
.completion(cs -> cs //
|
||||
.field("suggest") //
|
||||
.fuzzy(SuggestFuzziness.of(f -> f.fuzziness("AUTO"))) //
|
||||
.contexts( //
|
||||
ContextCompletionEntity.LANGUAGE_CATEGORY, //
|
||||
List.of(CompletionContext.of(cc -> cc //
|
||||
.context(cb -> cb.category(category)) //
|
||||
)) //
|
||||
) //
|
||||
) //
|
||||
) //
|
||||
))) //
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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.suggest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilders;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
|
||||
import org.elasticsearch.xcontent.ToXContent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@ContextConfiguration(classes = { CompletionWithContextsERHLCIntegrationTests.Config.class })
|
||||
public class CompletionWithContextsERHLCIntegrationTests extends CompletionWithContextsIntegrationTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("completion-context-es7");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected Query getSearchQuery(String suggestionName, String category) {
|
||||
|
||||
CompletionSuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest")
|
||||
.prefix("m", Fuzziness.AUTO);
|
||||
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
List<CategoryQueryContext> contexts = new ArrayList<>(1);
|
||||
|
||||
CategoryQueryContext queryContext = CategoryQueryContext.builder().setCategory(category).build();
|
||||
contexts.add(queryContext);
|
||||
contextMap.put(ContextCompletionEntity.LANGUAGE_CATEGORY, contexts);
|
||||
|
||||
completionSuggestionFuzzyBuilder.contexts(contextMap);
|
||||
|
||||
var suggestBuilder = new SuggestBuilder().addSuggestion(suggestionName, completionSuggestionFuzzyBuilder);
|
||||
return new NativeSearchQueryBuilder().withSuggestBuilder(suggestBuilder).build();
|
||||
}
|
||||
|
||||
}
|
@ -15,38 +15,25 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.suggest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilders;
|
||||
import org.elasticsearch.search.suggest.SuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
|
||||
import org.elasticsearch.xcontent.ToXContent;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.CompletionContext;
|
||||
import org.springframework.data.elasticsearch.annotations.CompletionField;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.client.erhlc.ElasticsearchRestTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.suggest.response.Suggest;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.utils.IndexInitializer;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@ -56,24 +43,25 @@ import org.springframework.lang.Nullable;
|
||||
@SpringIntegrationTest
|
||||
public abstract class CompletionWithContextsIntegrationTests {
|
||||
|
||||
private static final String SUGGESTION_NAME = "test-suggest";
|
||||
|
||||
@Autowired private ElasticsearchOperations operations;
|
||||
private IndexOperations indexOperations;
|
||||
@Autowired private IndexNameProvider indexNameProvider;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
indexOperations = operations.indexOps(ContextCompletionEntity.class);
|
||||
indexOperations.delete();
|
||||
indexNameProvider.increment();
|
||||
operations.indexOps(ContextCompletionEntity.class).createWithMapping();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void after() {
|
||||
indexOperations.delete();
|
||||
@Test
|
||||
@Order(java.lang.Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + "*")).delete();
|
||||
}
|
||||
|
||||
private void loadContextCompletionObjectEntities() {
|
||||
|
||||
IndexInitializer.init(indexOperations);
|
||||
|
||||
NonDocumentEntity nonDocumentEntity = new NonDocumentEntity();
|
||||
nonDocumentEntity.setSomeField1("foo");
|
||||
nonDocumentEntity.setSomeField2("bar");
|
||||
@ -100,105 +88,74 @@ public abstract class CompletionWithContextsIntegrationTests {
|
||||
indexQueries.add(new ContextCompletionEntityBuilder("4").name("Artur Konczak")
|
||||
.suggest(new String[] { "Artur", "Konczak" }, context4).buildIndex());
|
||||
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of("test-index-context-completion"));
|
||||
operations.bulkIndex(indexQueries, IndexCoordinates.of(indexNameProvider.indexName()));
|
||||
operations.indexOps(ContextCompletionEntity.class).refresh();
|
||||
}
|
||||
|
||||
abstract protected Query getSearchQuery(String suggestionName, String category);
|
||||
|
||||
@Test // DATAES-536
|
||||
public void shouldFindSuggestionsForGivenCriteriaQueryUsingContextCompletionEntityOfMongo() {
|
||||
|
||||
// given
|
||||
loadContextCompletionObjectEntities();
|
||||
CompletionSuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest")
|
||||
.prefix("m", Fuzziness.AUTO);
|
||||
Query query = getSearchQuery(SUGGESTION_NAME, "mongo");
|
||||
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
List<CategoryQueryContext> contexts = new ArrayList<>(1);
|
||||
var searchHits = operations.search(query, ContextCompletionEntity.class);
|
||||
|
||||
CategoryQueryContext.Builder builder = CategoryQueryContext.builder();
|
||||
builder.setCategory("mongo");
|
||||
CategoryQueryContext queryContext = builder.build();
|
||||
contexts.add(queryContext);
|
||||
contextMap.put(ContextCompletionEntity.LANGUAGE_CATEGORY, contexts);
|
||||
|
||||
completionSuggestionFuzzyBuilder.contexts(contextMap);
|
||||
|
||||
// when
|
||||
SearchResponse suggestResponse = ((ElasticsearchRestTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
// then
|
||||
assertThat(searchHits.hasSuggest()).isTrue();
|
||||
Suggest suggest = searchHits.getSuggest();
|
||||
Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> suggestion = suggest
|
||||
.getSuggestion(SUGGESTION_NAME);
|
||||
assertThat(suggestion).isNotNull();
|
||||
assertThat(suggestion)
|
||||
.isInstanceOf(org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.class);
|
||||
List<org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.Entry.Option<CompletionIntegrationTests.AnnotatedCompletionEntity>> options = ((org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion<CompletionIntegrationTests.AnnotatedCompletionEntity>) suggestion)
|
||||
.getEntries().get(0).getOptions();
|
||||
assertThat(options).hasSize(1);
|
||||
assertThat(options.get(0).getText().string()).isEqualTo("Marchand");
|
||||
assertThat(options.get(0).getText()).isEqualTo("Marchand");
|
||||
}
|
||||
|
||||
@Test // DATAES-536
|
||||
public void shouldFindSuggestionsForGivenCriteriaQueryUsingContextCompletionEntityOfElastic() {
|
||||
|
||||
// given
|
||||
loadContextCompletionObjectEntities();
|
||||
SuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest").prefix("m",
|
||||
Fuzziness.AUTO);
|
||||
Query query = getSearchQuery(SUGGESTION_NAME, "elastic");
|
||||
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
List<CategoryQueryContext> contexts = new ArrayList<>(1);
|
||||
var searchHits = operations.search(query, ContextCompletionEntity.class);
|
||||
|
||||
CategoryQueryContext.Builder builder = CategoryQueryContext.builder();
|
||||
builder.setCategory("elastic");
|
||||
CategoryQueryContext queryContext = builder.build();
|
||||
contexts.add(queryContext);
|
||||
contextMap.put(ContextCompletionEntity.LANGUAGE_CATEGORY, contexts);
|
||||
|
||||
((CompletionSuggestionBuilder) completionSuggestionFuzzyBuilder).contexts(contextMap);
|
||||
|
||||
// when
|
||||
SearchResponse suggestResponse = ((ElasticsearchRestTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
// then
|
||||
assertThat(searchHits.hasSuggest()).isTrue();
|
||||
Suggest suggest = searchHits.getSuggest();
|
||||
Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> suggestion = suggest
|
||||
.getSuggestion(SUGGESTION_NAME);
|
||||
assertThat(suggestion).isNotNull();
|
||||
assertThat(suggestion)
|
||||
.isInstanceOf(org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.class);
|
||||
List<org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.Entry.Option<CompletionIntegrationTests.AnnotatedCompletionEntity>> options = ((org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion<CompletionIntegrationTests.AnnotatedCompletionEntity>) suggestion)
|
||||
.getEntries().get(0).getOptions();
|
||||
assertThat(options).hasSize(1);
|
||||
assertThat(options.get(0).getText().string()).isEqualTo("Mohsin");
|
||||
assertThat(options.get(0).getText()).isEqualTo("Mohsin");
|
||||
}
|
||||
|
||||
@Test // DATAES-536
|
||||
public void shouldFindSuggestionsForGivenCriteriaQueryUsingContextCompletionEntityOfKotlin() {
|
||||
|
||||
// given
|
||||
loadContextCompletionObjectEntities();
|
||||
SuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest").prefix("m",
|
||||
Fuzziness.AUTO);
|
||||
Query query = getSearchQuery(SUGGESTION_NAME, "kotlin");
|
||||
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
List<CategoryQueryContext> contexts = new ArrayList<>(1);
|
||||
var searchHits = operations.search(query, ContextCompletionEntity.class);
|
||||
|
||||
CategoryQueryContext.Builder builder = CategoryQueryContext.builder();
|
||||
builder.setCategory("kotlin");
|
||||
CategoryQueryContext queryContext = builder.build();
|
||||
contexts.add(queryContext);
|
||||
contextMap.put(ContextCompletionEntity.LANGUAGE_CATEGORY, contexts);
|
||||
|
||||
((CompletionSuggestionBuilder) completionSuggestionFuzzyBuilder).contexts(contextMap);
|
||||
|
||||
// when
|
||||
SearchResponse suggestResponse = ((ElasticsearchRestTemplate) operations).suggest(
|
||||
new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder),
|
||||
IndexCoordinates.of("test-index-context-completion"));
|
||||
assertThat(suggestResponse.getSuggest()).isNotNull();
|
||||
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
|
||||
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
|
||||
|
||||
// then
|
||||
assertThat(searchHits.hasSuggest()).isTrue();
|
||||
Suggest suggest = searchHits.getSuggest();
|
||||
Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> suggestion = suggest
|
||||
.getSuggestion(SUGGESTION_NAME);
|
||||
assertThat(suggestion).isNotNull();
|
||||
assertThat(suggestion)
|
||||
.isInstanceOf(org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.class);
|
||||
List<org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion.Entry.Option<CompletionIntegrationTests.AnnotatedCompletionEntity>> options = ((org.springframework.data.elasticsearch.core.suggest.response.CompletionSuggestion<CompletionIntegrationTests.AnnotatedCompletionEntity>) suggestion)
|
||||
.getEntries().get(0).getOptions();
|
||||
assertThat(options).hasSize(2);
|
||||
assertThat(options.get(0).getText().string()).isIn("Marchand", "Mohsin");
|
||||
assertThat(options.get(1).getText().string()).isIn("Marchand", "Mohsin");
|
||||
assertThat(options.get(0).getText()).isIn("Marchand", "Mohsin");
|
||||
assertThat(options.get(1).getText()).isIn("Marchand", "Mohsin");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,7 +192,7 @@ public abstract class CompletionWithContextsIntegrationTests {
|
||||
* @author Mewes Kochheim
|
||||
* @author Robert Gruendler
|
||||
*/
|
||||
@Document(indexName = "test-index-context-completion")
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class ContextCompletionEntity {
|
||||
|
||||
public static final String LANGUAGE_CATEGORY = "language";
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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.suggest;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ContextConfiguration(classes = { CompletionWithContextsRestTemplateIntegrationTests.Config.class })
|
||||
public class CompletionWithContextsRestTemplateIntegrationTests extends CompletionWithContextsIntegrationTests {
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
}
|
@ -18,7 +18,7 @@ package org.springframework.data.elasticsearch.repositories.setting.dynamic;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@ -32,7 +32,7 @@ public class DynamicSettingAndMappingEntityRepositoryELCIntegrationTests
|
||||
extends DynamicSettingAndMappingEntityRepositoryIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
@Import({ ElasticsearchTemplateConfiguration.class })
|
||||
@EnableElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
@Bean
|
||||
|
@ -71,7 +71,7 @@ public abstract class DynamicSettingAndMappingEntityRepositoryIntegrationTests {
|
||||
public void shouldCreateGivenDynamicSettingsForGivenIndex() {
|
||||
|
||||
assertThat(indexOperations.exists()).isTrue();
|
||||
Map<String, Object> map = indexOperations.getSettings();
|
||||
Map<String, Object> map = indexOperations.getSettings().flatten();
|
||||
assertThat(map.containsKey("index.number_of_replicas")).isTrue();
|
||||
assertThat(map.containsKey("index.number_of_shards")).isTrue();
|
||||
assertThat(map.containsKey("index.analysis.analyzer.emailAnalyzer.tokenizer")).isTrue();
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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.utils;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.IndexOperations;
|
||||
|
||||
/**
|
||||
* Utility to initialize indexes.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class IndexInitializer {
|
||||
|
||||
private IndexInitializer() {}
|
||||
|
||||
/**
|
||||
* Initialize a fresh index with mappings for {@link Class}. Drops the index if it exists before creation.
|
||||
*
|
||||
* @param indexOperations
|
||||
*/
|
||||
public static void init(IndexOperations indexOperations) {
|
||||
indexOperations.delete();
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(indexOperations.createMapping());
|
||||
indexOperations.refresh();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user