DATAES-504 - Add ReactiveElasticsearchOperations & ReactiveElasticsearchTemplate
ReactiveElasticsearchOperations is the gateway to executing high level commands against an Elasticsearch cluster using the ReactiveElasticsearchClient.
The ReactiveElasticsearchTemplate is the default implementation of ReactiveElasticsearchOperations and offers the following set of features.
* Read/Write mapping support for domain types.
* A rich query and criteria api.
* Resource management and Exception translation.
To get started the ReactiveElasticsearchTemplate needs to know about the actual client to work with.
The easiest way of setting up the ReactiveElasticsearchTemplate is via AbstractReactiveElasticsearchConfiguration providing
dedicated configuration method hooks for base package, the initial entity set etc.
@Configuration
public class Config extends AbstractReactiveElasticsearchConfiguration {
@Bean
@Override
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
// ...
}
}
NOTE: If applicable set default HttpHeaders via the ClientConfiguration of the ReactiveElasticsearchClient.
TIP: If needed the ReactiveElasticsearchTemplate can be configured with default RefreshPolicy and IndicesOptions that get applied to the related requests by overriding the defaults of refreshPolicy() and indicesOptions().
The ReactiveElasticsearchTemplate lets you save, find and delete your domain objects and map those objects to documents stored in Elasticsearch.
@Document(indexName = "marvel", type = "characters")
public class Person {
private @Id String id;
private String name;
private int age;
// Getter/Setter omitted...
}
template.save(new Person("Bruce Banner", 42)) // save a new document
.doOnNext(System.out::println)
.flatMap(person -> template.findById(person.id, Person.class)) // then go find it
.doOnNext(System.out::println)
.flatMap(person -> template.delete(person)) // just to remove remove it again
.doOnNext(System.out::println)
.flatMap(id -> template.count(Person.class)) // so we've got nothing at the end
.doOnNext(System.out::println)
.subscribe(); // yeah :)
The above outputs the following sequence on the console.
> Person(id=QjWCWWcBXiLAnp77ksfR, name=Bruce Banner, age=42)
> Person(id=QjWCWWcBXiLAnp77ksfR, name=Bruce Banner, age=42)
> QjWCWWcBXiLAnp77ksfR
> 0
Original Pull Request: #229
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Documented
|
||||
public @interface ElasticsearchVersion {
|
||||
|
||||
/**
|
||||
* Inclusive lower bound of Elasticsearch server range.
|
||||
*
|
||||
* @return {@code 0.0.0} by default.
|
||||
*/
|
||||
String asOf() default "0.0.0";
|
||||
|
||||
/**
|
||||
* Exclusive upper bound of Elasticsearch server range.
|
||||
*
|
||||
* @return {@code 9999.9999.9999} by default.
|
||||
*/
|
||||
String until() default "9999.9999.9999";
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.AssumptionViolatedException;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.util.Version;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ElasticsearchVersionRule implements TestRule {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ElasticsearchVersionRule.class);
|
||||
|
||||
private static final Version ANY = new Version(9999, 9999, 9999);
|
||||
private static final Version DEFAULT_HIGH = ANY;
|
||||
private static final Version DEFAULT_LOW = new Version(0, 0, 0);
|
||||
|
||||
private final static AtomicReference<Version> currentVersion = new AtomicReference<>(null);
|
||||
private final Version minVersion;
|
||||
private final Version maxVersion;
|
||||
|
||||
public ElasticsearchVersionRule(Version min, Version max) {
|
||||
|
||||
this.minVersion = min;
|
||||
this.maxVersion = max;
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule any() {
|
||||
return new ElasticsearchVersionRule(ANY, ANY);
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule atLeast(Version minVersion) {
|
||||
return new ElasticsearchVersionRule(minVersion, DEFAULT_HIGH);
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule atMost(Version maxVersion) {
|
||||
return new ElasticsearchVersionRule(DEFAULT_LOW, maxVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(final Statement base, Description description) {
|
||||
|
||||
return new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
|
||||
if (!getCurrentVersion().equals(ANY)) {
|
||||
|
||||
Version minVersion = ElasticsearchVersionRule.this.minVersion.equals(ANY) ? DEFAULT_LOW
|
||||
: ElasticsearchVersionRule.this.minVersion;
|
||||
Version maxVersion = ElasticsearchVersionRule.this.maxVersion.equals(ANY) ? DEFAULT_HIGH
|
||||
: ElasticsearchVersionRule.this.maxVersion;
|
||||
|
||||
if (description.getAnnotation(ElasticsearchVersion.class) != null) {
|
||||
ElasticsearchVersion version = description.getAnnotation(ElasticsearchVersion.class);
|
||||
if (version != null) {
|
||||
|
||||
Version expectedMinVersion = Version.parse(version.asOf());
|
||||
if (!expectedMinVersion.equals(ANY) && !expectedMinVersion.equals(DEFAULT_LOW)) {
|
||||
minVersion = expectedMinVersion;
|
||||
}
|
||||
|
||||
Version expectedMaxVersion = Version.parse(version.until());
|
||||
if (!expectedMaxVersion.equals(ANY) && !expectedMaxVersion.equals(DEFAULT_HIGH)) {
|
||||
maxVersion = expectedMaxVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validateVersion(minVersion, maxVersion);
|
||||
}
|
||||
|
||||
base.evaluate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void validateVersion(Version min, Version max) {
|
||||
|
||||
if (getCurrentVersion().isLessThan(min) || getCurrentVersion().isGreaterThanOrEqualTo(max)) {
|
||||
|
||||
throw new AssumptionViolatedException(String
|
||||
.format("Expected Elasticsearch server to be in range (%s, %s] but found %s", min, max, currentVersion));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Version getCurrentVersion() {
|
||||
|
||||
if (currentVersion.get() == null) {
|
||||
|
||||
Version current = fetchCurrentVersion();
|
||||
if (currentVersion.compareAndSet(null, current)) {
|
||||
logger.info("Running Elasticsearch " + current);
|
||||
}
|
||||
}
|
||||
|
||||
return currentVersion.get();
|
||||
}
|
||||
|
||||
private Version fetchCurrentVersion() {
|
||||
return TestUtils.serverVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCurrentVersion().toString();
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,20 @@ package org.springframework.data.elasticsearch;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.RestClients;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
|
||||
import org.springframework.data.util.Version;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -44,6 +49,18 @@ public final class TestUtils {
|
||||
return ReactiveRestClients.create(ClientConfiguration.create("localhost:9200"));
|
||||
}
|
||||
|
||||
public static Version serverVersion() {
|
||||
|
||||
try (RestHighLevelClient client = restHighLevelClient()) {
|
||||
|
||||
org.elasticsearch.Version version = client.info(RequestOptions.DEFAULT).getVersion();
|
||||
return new Version(version.major, version.minor, version.revision);
|
||||
|
||||
} catch (Exception e) {
|
||||
return new Version(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static void deleteIndex(String... indexes) {
|
||||
|
||||
@@ -62,4 +79,48 @@ public final class TestUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static OfType documentWithId(String id) {
|
||||
return new DocumentLookup(id);
|
||||
}
|
||||
|
||||
public interface ExistsIn {
|
||||
boolean existsIn(String index);
|
||||
}
|
||||
|
||||
public interface OfType extends ExistsIn {
|
||||
ExistsIn ofType(String type);
|
||||
}
|
||||
|
||||
private static class DocumentLookup implements OfType {
|
||||
|
||||
private String id;
|
||||
private String type;
|
||||
|
||||
public DocumentLookup(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsIn(String index) {
|
||||
|
||||
GetRequest request = new GetRequest(index).id(id);
|
||||
if (StringUtils.hasText(type)) {
|
||||
request = request.type(type);
|
||||
}
|
||||
try {
|
||||
return restHighLevelClient().get(request, RequestOptions.DEFAULT).isExists();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExistsIn ofType(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ package org.springframework.data.elasticsearch.client.reactive;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchVersion;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchVersionRule;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -37,6 +40,7 @@ import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.junit.After;
|
||||
@@ -58,6 +62,8 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class ReactiveElasticsearchClientTests {
|
||||
|
||||
public @Rule ElasticsearchVersionRule elasticsearchVersion = ElasticsearchVersionRule.any();
|
||||
|
||||
static final String INDEX_I = "idx-1-reactive-client-tests";
|
||||
static final String INDEX_II = "idx-2-reactive-client-tests";
|
||||
|
||||
@@ -413,6 +419,43 @@ public class ReactiveElasticsearchClientTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByShouldRemoveExistingDocument() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
|
||||
DeleteByQueryRequest request = new DeleteByQueryRequest(INDEX_I) //
|
||||
.setDocTypes(TYPE_I) //
|
||||
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("_id", id)));
|
||||
|
||||
client.deleteBy(request) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> {
|
||||
|
||||
assertThat(it.getDeleted()).isEqualTo(1);
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByEmitResultWhenNothingRemoved() {
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
|
||||
DeleteByQueryRequest request = new DeleteByQueryRequest(INDEX_I) //
|
||||
.setDocTypes(TYPE_I) //
|
||||
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("_id", "it-was-not-me")));
|
||||
|
||||
client.deleteBy(request) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> {
|
||||
assertThat(it.getDeleted()).isEqualTo(0);
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
AddToIndexOfType addSourceDocument() {
|
||||
return add(DOC_SOURCE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.lang.ClassUtils;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ElasticsearchConfigurationSupportUnitTests {
|
||||
|
||||
@Test // DATAES-504
|
||||
public void usesConfigClassPackageAsBaseMappingPackage() throws ClassNotFoundException {
|
||||
|
||||
ElasticsearchConfigurationSupport configuration = new StubConfig();
|
||||
assertThat(configuration.getMappingBasePackages()).contains(ClassUtils.getPackageName(StubConfig.class));
|
||||
assertThat(configuration.getInitialEntitySet()).contains(Entity.class);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void doesNotScanOnEmptyBasePackage() throws ClassNotFoundException {
|
||||
|
||||
ElasticsearchConfigurationSupport configuration = new StubConfig() {
|
||||
@Override
|
||||
protected Collection<String> getMappingBasePackages() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(configuration.getInitialEntitySet()).isEmpty();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void containsMappingContext() {
|
||||
|
||||
AbstractApplicationContext context = new AnnotationConfigApplicationContext(StubConfig.class);
|
||||
assertThat(context.getBean(SimpleElasticsearchMappingContext.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void containsElasticsearchConverter() {
|
||||
|
||||
AbstractApplicationContext context = new AnnotationConfigApplicationContext(StubConfig.class);
|
||||
assertThat(context.getBean(ElasticsearchConverter.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void restConfigContainsElasticsearchTemplate() {
|
||||
|
||||
AbstractApplicationContext context = new AnnotationConfigApplicationContext(RestConfig.class);
|
||||
assertThat(context.getBean(ElasticsearchRestTemplate.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void reactiveConfigContainsReactiveElasticsearchTemplate() {
|
||||
|
||||
AbstractApplicationContext context = new AnnotationConfigApplicationContext(ReactiveRestConfig.class);
|
||||
assertThat(context.getBean(ReactiveElasticsearchTemplate.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class StubConfig extends ElasticsearchConfigurationSupport {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ReactiveRestConfig extends AbstractReactiveElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
|
||||
return mock(ReactiveElasticsearchClient.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class RestConfig extends AbstractElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
public RestHighLevelClient elasticsearchClient() {
|
||||
return mock(RestHighLevelClient.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Document(indexName = "config-support-tests")
|
||||
static class Entity {}
|
||||
}
|
||||
@@ -15,24 +15,42 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchVersion;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchVersionRule;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -42,16 +60,20 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
public @Rule ElasticsearchVersionRule elasticsearchVersion = ElasticsearchVersionRule.any();
|
||||
|
||||
static final String DEFAULT_INDEX = "test-index-sample";
|
||||
static final String ALTERNATE_INDEX = "reactive-template-tests-alternate-index";
|
||||
|
||||
private ElasticsearchRestTemplate restTemplate;
|
||||
private ReactiveElasticsearchTemplate template;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
TestUtils.deleteIndex(DEFAULT_INDEX, ALTERNATE_INDEX);
|
||||
|
||||
restTemplate = new ElasticsearchRestTemplate(TestUtils.restHighLevelClient());
|
||||
|
||||
TestUtils.deleteIndex("test-index-sample");
|
||||
|
||||
restTemplate.createIndex(SampleEntity.class);
|
||||
restTemplate.putMapping(SampleEntity.class);
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
@@ -59,14 +81,35 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
template = new ReactiveElasticsearchTemplate(TestUtils.reactiveClient());
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
public void indexWithIdShouldWork() {
|
||||
@Test // DATAES-504
|
||||
public void executeShouldProvideResource() {
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("foo bar")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
Mono.from(template.execute(client -> client.ping())) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
template.index(sampleEntity).as(StepVerifier::create).expectNextCount(1).verifyComplete();
|
||||
@Test // DATAES-504
|
||||
public void executeShouldConvertExceptions() {
|
||||
|
||||
Mono.from(template.execute(client -> {
|
||||
throw new RuntimeException(new ConnectException("we're doomed"));
|
||||
})) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectError(DataAccessResourceFailureException.class) //
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertWithIdShouldWork() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("foo bar");
|
||||
|
||||
template.save(sampleEntity)//
|
||||
.as(StepVerifier::create)//
|
||||
.expectNextCount(1)//
|
||||
.verifyComplete();
|
||||
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
|
||||
@@ -75,78 +118,388 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
assertThat(result).hasSize(1);
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
public void getShouldReturnEntity() {
|
||||
@Test // DATAES-504
|
||||
public void insertWithAutogeneratedIdShouldUpdateEntityId() {
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntity = SampleEntity.builder().message("wohoo").build();
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
restTemplate.index(indexQuery);
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
template.save(sampleEntity) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> {
|
||||
|
||||
template.get(documentId, SampleEntity.class) //
|
||||
assertThat(it.getId()).isNotNull();
|
||||
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
assertThat(TestUtils.documentWithId(it.getId()).existsIn(DEFAULT_INDEX)).isTrue();
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertWithExplicitIndexNameShouldOverwriteMetadata() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("in another index");
|
||||
|
||||
template.save(sampleEntity, ALTERNATE_INDEX).as(StepVerifier::create)//
|
||||
.expectNextCount(1)//
|
||||
.verifyComplete();
|
||||
|
||||
restTemplate.refresh(DEFAULT_INDEX);
|
||||
restTemplate.refresh(ALTERNATE_INDEX);
|
||||
|
||||
assertThat(TestUtils.documentWithId(sampleEntity.getId()).existsIn(DEFAULT_INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId(sampleEntity.getId()).existsIn(ALTERNATE_INDEX)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertShouldAcceptPlainMapStructureAsSource() {
|
||||
|
||||
Map<String, Object> map = Collections.singletonMap("foo", "bar");
|
||||
|
||||
template.save(map, ALTERNATE_INDEX, "singleton-map") //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATAES-504
|
||||
public void insertShouldErrorOnNullEntity() {
|
||||
template.save(null);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void findByIdShouldReturnEntity() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.findById(sampleEntity.getId(), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
public void getForNothing() {
|
||||
@Test // DATAES-504
|
||||
public void findByIdWhenIdIsAutogeneratedShouldHaveIdSetCorrectly() {
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntity = new SampleEntity();
|
||||
sampleEntity.setMessage("some message");
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
restTemplate.index(indexQuery);
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
index(sampleEntity);
|
||||
|
||||
template.get("foo", SampleEntity.class) //
|
||||
assertThat(sampleEntity.getId()).isNotNull();
|
||||
|
||||
template.findById(sampleEntity.getId(), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo(sampleEntity.getId())) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void findByIdShouldCompleteWhenNotingFound() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.findById("foo", SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
public void findShouldApplyCriteria() {
|
||||
@Test(expected = IllegalArgumentException.class) // DATAES-504
|
||||
public void findByIdShouldErrorForNullId() {
|
||||
template.findById(null, SampleEntity.class);
|
||||
}
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
@Test // DATAES-504
|
||||
public void findByIdWithExplicitIndexNameShouldOverwriteMetadata() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
indexQuery.setIndexName(ALTERNATE_INDEX);
|
||||
|
||||
restTemplate.index(indexQuery);
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
|
||||
restTemplate.refresh(DEFAULT_INDEX);
|
||||
restTemplate.refresh(ALTERNATE_INDEX);
|
||||
|
||||
template.findById(sampleEntity.getId(), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
template.findById(sampleEntity.getId(), SampleEntity.class, ALTERNATE_INDEX) //
|
||||
.as(StepVerifier::create)//
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void existsShouldReturnTrueWhenFound() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.exists(sampleEntity.getId(), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void existsShouldReturnFalseWhenNotFound() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.exists("foo", SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(false) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void findShouldApplyCriteria() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(Criteria.where("message").is("some message"));
|
||||
|
||||
template.query(criteriaQuery, SampleEntity.class) //
|
||||
template.find(criteriaQuery, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@Test // DATAES-504
|
||||
public void findShouldReturnEmptyFluxIfNothingFound() {
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
restTemplate.index(indexQuery);
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
index(sampleEntity);
|
||||
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(Criteria.where("message").is("foo"));
|
||||
|
||||
template.query(criteriaQuery, SampleEntity.class) //
|
||||
template.find(criteriaQuery, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void shouldAllowStringBasedQuery() {
|
||||
|
||||
index(randomEntity("test message"), randomEntity("test test"), randomEntity("some message"));
|
||||
|
||||
template.find(new StringQuery(matchAllQuery().toString()), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(3) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void shouldExecuteGivenCriteriaQuery() {
|
||||
|
||||
SampleEntity shouldMatch = randomEntity("test message");
|
||||
SampleEntity shouldNotMatch = randomEntity("the dog ate my homework");
|
||||
index(shouldMatch, shouldNotMatch);
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("message").contains("test"));
|
||||
|
||||
template.find(query, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(shouldMatch) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void shouldReturnListForGivenCriteria() {
|
||||
|
||||
SampleEntity sampleEntity1 = randomEntity("test message");
|
||||
SampleEntity sampleEntity2 = randomEntity("test test");
|
||||
SampleEntity sampleEntity3 = randomEntity("some message");
|
||||
|
||||
index(sampleEntity1, sampleEntity2, sampleEntity3);
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(
|
||||
new Criteria("message").contains("some").and("message").contains("message"));
|
||||
|
||||
template.find(query, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(sampleEntity3) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void shouldReturnProjectedTargetEntity() {
|
||||
|
||||
SampleEntity sampleEntity1 = randomEntity("test message");
|
||||
SampleEntity sampleEntity2 = randomEntity("test test");
|
||||
SampleEntity sampleEntity3 = randomEntity("some message");
|
||||
|
||||
index(sampleEntity1, sampleEntity2, sampleEntity3);
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(
|
||||
new Criteria("message").contains("some").and("message").contains("message"));
|
||||
|
||||
template.find(query, SampleEntity.class, Message.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(new Message(sampleEntity3.getMessage())) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void countShouldReturnCountAllWhenGivenNoQuery() {
|
||||
|
||||
index(randomEntity("test message"), randomEntity("test test"), randomEntity("some message"));
|
||||
|
||||
template.count(SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(3L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void countShouldReturnCountMatchingDocuments() {
|
||||
|
||||
index(randomEntity("test message"), randomEntity("test test"), randomEntity("some message"));
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("message").contains("test"));
|
||||
|
||||
template.count(query, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByIdShouldRemoveExistingDocumentById() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("test message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.deleteById(sampleEntity.getId(), SampleEntity.class) //
|
||||
.as(StepVerifier::create)//
|
||||
.expectNext(sampleEntity.getId()) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteShouldRemoveExistingDocumentByIdUsingIndexName() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("test message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.deleteById(sampleEntity.getId(), DEFAULT_INDEX, "test-type") //
|
||||
.as(StepVerifier::create)//
|
||||
.expectNext(sampleEntity.getId()) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteShouldRemoveExistingDocument() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("test message");
|
||||
index(sampleEntity);
|
||||
|
||||
template.delete(sampleEntity) //
|
||||
.as(StepVerifier::create)//
|
||||
.expectNext(sampleEntity.getId()) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByIdShouldCompleteWhenNothingDeleted() {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("test message");
|
||||
|
||||
template.delete(sampleEntity) //
|
||||
.as(StepVerifier::create)//
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByQueryShouldReturnNumberOfDeletedDocuments() {
|
||||
|
||||
index(randomEntity("test message"), randomEntity("test test"), randomEntity("some message"));
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("message").contains("test"));
|
||||
|
||||
template.deleteBy(query, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByQueryShouldReturnZeroIfNothingDeleted() {
|
||||
|
||||
index(randomEntity("test message"));
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("message").contains("luke"));
|
||||
|
||||
template.deleteBy(query, SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(0L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Data
|
||||
@Document(indexName = "marvel", type = "characters")
|
||||
static class Person {
|
||||
|
||||
private @Id String id;
|
||||
private String name;
|
||||
private int age;
|
||||
|
||||
public Person() {}
|
||||
|
||||
public Person(String name, int age) {
|
||||
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check field mapping !!!
|
||||
|
||||
// --> JUST some helpers
|
||||
|
||||
private SampleEntity randomEntity(String message) {
|
||||
|
||||
return SampleEntity.builder() //
|
||||
.id(UUID.randomUUID().toString()) //
|
||||
.message(StringUtils.hasText(message) ? message : "test message") //
|
||||
.version(System.currentTimeMillis()).build();
|
||||
}
|
||||
|
||||
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
|
||||
|
||||
return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity)
|
||||
.withVersion(sampleEntity.getVersion()).build();
|
||||
}
|
||||
|
||||
private List<IndexQuery> getIndexQueries(SampleEntity... sampleEntities) {
|
||||
return Arrays.stream(sampleEntities).map(this::getIndexQuery).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void index(SampleEntity... entities) {
|
||||
|
||||
if (entities.length == 1) {
|
||||
restTemplate.index(getIndexQuery(entities[0]));
|
||||
} else {
|
||||
restTemplate.bulkIndex(getIndexQueries(entities));
|
||||
}
|
||||
|
||||
restTemplate.refresh(SampleEntity.class);
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
static class Message {
|
||||
String message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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.assertj.core.api.Assertions.*;
|
||||
import static org.elasticsearch.action.search.SearchRequest.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @currentRead Fool's Fate - Robin Hobb
|
||||
*/
|
||||
public class ReactiveElasticsearchTemplateUnitTests {
|
||||
|
||||
@Rule //
|
||||
public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Mock ReactiveElasticsearchClient client;
|
||||
ReactiveElasticsearchTemplate template;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
template = new ReactiveElasticsearchTemplate(client);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertShouldUseDefaultRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<IndexRequest> captor = ArgumentCaptor.forClass(IndexRequest.class);
|
||||
when(client.index(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.save(Collections.singletonMap("key", "value"), "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().getRefreshPolicy()).isEqualTo(RefreshPolicy.IMMEDIATE);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertShouldApplyRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<IndexRequest> captor = ArgumentCaptor.forClass(IndexRequest.class);
|
||||
when(client.index(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL);
|
||||
|
||||
template.save(Collections.singletonMap("key", "value"), "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().getRefreshPolicy()).isEqualTo(RefreshPolicy.WAIT_UNTIL);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void findShouldFallBackToDefaultIndexOptionsIfNotSet() {
|
||||
|
||||
ArgumentCaptor<SearchRequest> captor = ArgumentCaptor.forClass(SearchRequest.class);
|
||||
when(client.search(captor.capture())).thenReturn(Flux.empty());
|
||||
|
||||
template.find(new CriteriaQuery(new Criteria("*")), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().indicesOptions()).isEqualTo(DEFAULT_INDICES_OPTIONS);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void findShouldApplyIndexOptionsIfSet() {
|
||||
|
||||
ArgumentCaptor<SearchRequest> captor = ArgumentCaptor.forClass(SearchRequest.class);
|
||||
when(client.search(captor.capture())).thenReturn(Flux.empty());
|
||||
|
||||
template.setIndicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
|
||||
|
||||
template.find(new CriteriaQuery(new Criteria("*")), SampleEntity.class) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().indicesOptions()).isEqualTo(IndicesOptions.LENIENT_EXPAND_OPEN);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteShouldUseDefaultRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<DeleteRequest> captor = ArgumentCaptor.forClass(DeleteRequest.class);
|
||||
when(client.delete(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.deleteById("id", "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().getRefreshPolicy()).isEqualTo(RefreshPolicy.IMMEDIATE);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteShouldApplyRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<DeleteRequest> captor = ArgumentCaptor.forClass(DeleteRequest.class);
|
||||
when(client.delete(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL);
|
||||
|
||||
template.deleteById("id", "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().getRefreshPolicy()).isEqualTo(RefreshPolicy.WAIT_UNTIL);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByShouldUseDefaultRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<DeleteByQueryRequest> captor = ArgumentCaptor.forClass(DeleteByQueryRequest.class);
|
||||
when(client.deleteBy(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.deleteBy(new StringQuery(QueryBuilders.matchAllQuery().toString()), Object.class, "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().isRefresh()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByShouldApplyRefreshPolicy() {
|
||||
|
||||
ArgumentCaptor<DeleteByQueryRequest> captor = ArgumentCaptor.forClass(DeleteByQueryRequest.class);
|
||||
when(client.deleteBy(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.setRefreshPolicy(RefreshPolicy.NONE);
|
||||
|
||||
template.deleteBy(new StringQuery(QueryBuilders.matchAllQuery().toString()), Object.class, "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().isRefresh()).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByShouldApplyIndicesOptions() {
|
||||
|
||||
ArgumentCaptor<DeleteByQueryRequest> captor = ArgumentCaptor.forClass(DeleteByQueryRequest.class);
|
||||
when(client.deleteBy(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.deleteBy(new StringQuery(QueryBuilders.matchAllQuery().toString()), Object.class, "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().indicesOptions()).isEqualTo(DEFAULT_INDICES_OPTIONS);
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void deleteByShouldApplyIndicesOptionsIfSet() {
|
||||
|
||||
ArgumentCaptor<DeleteByQueryRequest> captor = ArgumentCaptor.forClass(DeleteByQueryRequest.class);
|
||||
when(client.deleteBy(captor.capture())).thenReturn(Mono.empty());
|
||||
|
||||
template.setIndicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
|
||||
|
||||
template.deleteBy(new StringQuery(QueryBuilders.matchAllQuery().toString()), Object.class, "index", "type") //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(captor.getValue().indicesOptions()).isEqualTo(IndicesOptions.LENIENT_EXPAND_OPEN);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user