DATAES-612 - Add support for index templates.

Original PR: #495
This commit is contained in:
Peter-Josef Meisch 2020-07-17 21:11:40 +02:00 committed by GitHub
parent 0944d1654a
commit bdcecd0950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1836 additions and 116 deletions

View File

@ -7,6 +7,7 @@
* Upgrade to Elasticsearch 7.8.0
* Improved API for alias management
* Introduction of `ReactiveIndexOperations` for index management
* Index templates support
[[new-features.4-0-0]]
== New in Spring Data Elasticsearch 4.0

View File

@ -25,7 +25,7 @@ import org.springframework.lang.Nullable;
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Peter-Josef Meisch
* @deprecated since 4.0, use {@link org.springframework.dao.UncategorizedDataAccessException}
* @deprecated since 4.0, use {@link UncategorizedElasticsearchException}
*/
@Deprecated
public class ElasticsearchException extends RuntimeException {

View File

@ -64,6 +64,7 @@ import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
@ -86,6 +87,10 @@ import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
@ -266,10 +271,9 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
Optional<SSLContext> sslContext = clientConfiguration.getSslContext();
if (sslContext.isPresent()) {
httpClient = httpClient.secure(sslContextSpec -> {
sslContextSpec.sslContext(new JdkSslContext(sslContext.get(), true, null, IdentityCipherSuiteFilter.INSTANCE,
ApplicationProtocolConfig.DISABLED, ClientAuth.NONE, null, false));
});
httpClient = httpClient
.secure(sslContextSpec -> sslContextSpec.sslContext(new JdkSslContext(sslContext.get(), true, null,
IdentityCipherSuiteFilter.INSTANCE, ApplicationProtocolConfig.DISABLED, ClientAuth.NONE, null, false)));
} else {
httpClient = httpClient.secure();
}
@ -589,8 +593,8 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
// -->
private <Req extends ActionRequest, Resp> Flux<Resp> sendRequest(Req request, Function<Req, Request> converter,
Class<Resp> responseType, HttpHeaders headers) {
private <REQ, RESP> Flux<RESP> sendRequest(REQ request, Function<REQ, Request> converter, Class<RESP> responseType,
HttpHeaders headers) {
return sendRequest(converter.apply(request), responseType, headers);
}
@ -737,6 +741,32 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
return sendRequest(getAliasesRequest, requestCreator.getAlias(), GetAliasesResponse.class, headers).publishNext();
}
@Override
public Mono<Boolean> putTemplate(HttpHeaders headers, PutIndexTemplateRequest putIndexTemplateRequest) {
return sendRequest(putIndexTemplateRequest, requestCreator.putTemplate(), AcknowledgedResponse.class, headers)
.map(AcknowledgedResponse::isAcknowledged).next();
}
@Override
public Mono<GetIndexTemplatesResponse> getTemplate(HttpHeaders headers,
GetIndexTemplatesRequest getIndexTemplatesRequest) {
return (sendRequest(getIndexTemplatesRequest, requestCreator.getTemplates(), GetIndexTemplatesResponse.class,
headers)).next();
}
@Override
public Mono<Boolean> existsTemplate(HttpHeaders headers, IndexTemplatesExistRequest indexTemplatesExistRequest) {
return sendRequest(indexTemplatesExistRequest, requestCreator.templatesExist(), RawActionResponse.class, headers) //
.flatMap(response -> response.releaseBody().thenReturn(response.statusCode().is2xxSuccessful())) //
.next();
}
@Override
public Mono<Boolean> deleteTemplate(HttpHeaders headers, DeleteIndexTemplateRequest deleteIndexTemplateRequest) {
return sendRequest(deleteIndexTemplateRequest, requestCreator.deleteTemplate(), AcknowledgedResponse.class, headers)
.map(AcknowledgedResponse::isAcknowledged).next();
}
// endregion
// region helper functions
@ -758,7 +788,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
if (response.statusCode().is4xxClientError()) {
ClientLogger.logRawResponse(logId, response.statusCode());
return handleClientError(logId, request, response, responseType);
return handleClientError(logId, response, responseType);
}
return response.body(BodyExtractors.toMono(byte[].class)) //
@ -825,8 +855,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
request.getMethod(), request.getEndpoint(), statusCode), status)));
}
private <T> Publisher<? extends T> handleClientError(String logId, Request request, ClientResponse response,
Class<T> responseType) {
private <T> Publisher<? extends T> handleClientError(String logId, ClientResponse response, Class<T> responseType) {
int statusCode = response.statusCode().value();
RestStatus status = RestStatus.fromCode(statusCode);
@ -874,12 +903,13 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
try {
XContentParser parser = createParser(mediaType, content);
// we have a JSON object with an error and a status field
XContentParser.Token token = parser.nextToken(); // Skip START_OBJECT
parser.nextToken(); // Skip START_OBJECT
XContentParser.Token token;
do {
token = parser.nextToken();
if (parser.currentName().equals("error")) {
if ("error".equals(parser.currentName())) {
return ElasticsearchException.failureFromXContent(parser);
}
} while (token == XContentParser.Token.FIELD_NAME);
@ -906,7 +936,7 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
*
* @author Christoph Strobl
*/
class ClientStatus implements Status {
static class ClientStatus implements Status {
private final Collection<ElasticsearchHost> connectedHosts;

View File

@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
@ -50,6 +51,10 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
@ -610,6 +615,7 @@ public interface ReactiveElasticsearchClient {
* @param callback the {@link ReactiveElasticsearchClientCallback callback} wielding the actual command to run.
* @return the {@link Mono} emitting the {@link ClientResponse} once subscribed.
*/
@SuppressWarnings("JavaDoc")
Mono<ClientResponse> execute(ReactiveElasticsearchClientCallback callback);
/**
@ -1196,5 +1202,144 @@ public interface ReactiveElasticsearchClient {
* @since 4.1
*/
Mono<GetAliasesResponse> getAliases(HttpHeaders headers, GetAliasesRequest getAliasesRequest);
/**
* Execute the given {@link PutIndexTemplateRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion.
* @since 4.1
*/
default Mono<Boolean> putTemplate(Consumer<PutIndexTemplateRequest> consumer, String templateName) {
PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest(templateName);
consumer.accept(putIndexTemplateRequest);
return putTemplate(putIndexTemplateRequest);
}
/**
* Execute the given {@link PutIndexTemplateRequest} against the {@literal indices} API.
*
* @param putIndexTemplateRequest must not be {@literal null}
* @return a {@link Mono} signalling operation completion.
* @since 4.1
*/
default Mono<Boolean> putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) {
return putTemplate(HttpHeaders.EMPTY, putIndexTemplateRequest);
}
/**
* Execute the given {@link PutIndexTemplateRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param putIndexTemplateRequest must not be {@literal null}
* @return a {@link Mono} signalling operation completion.
* @since 4.1
*/
Mono<Boolean> putTemplate(HttpHeaders headers, PutIndexTemplateRequest putIndexTemplateRequest);
/**
* Execute the given {@link GetIndexTemplatesRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} with the GetIndexTemplatesResponse.
* @since 4.1
*/
default Mono<GetIndexTemplatesResponse> getTemplate(Consumer<GetIndexTemplatesRequest> consumer) {
GetIndexTemplatesRequest getIndexTemplatesRequest = new GetIndexTemplatesRequest();
consumer.accept(getIndexTemplatesRequest);
return getTemplate(getIndexTemplatesRequest);
}
/**
* Execute the given {@link GetIndexTemplatesRequest} against the {@literal indices} API.
*
* @param getIndexTemplatesRequest must not be {@literal null}
* @return a {@link Mono} with the GetIndexTemplatesResponse.
* @since 4.1
*/
default Mono<GetIndexTemplatesResponse> getTemplate(GetIndexTemplatesRequest getIndexTemplatesRequest) {
return getTemplate(HttpHeaders.EMPTY, getIndexTemplatesRequest);
}
/**
* Execute the given {@link GetIndexTemplatesRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getIndexTemplatesRequest must not be {@literal null}
* @return a {@link Mono} with the GetIndexTemplatesResponse.
* @since 4.1
*/
Mono<GetIndexTemplatesResponse> getTemplate(HttpHeaders headers, GetIndexTemplatesRequest getIndexTemplatesRequest);
/**
* Execute the given {@link IndexTemplatesExistRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
default Mono<Boolean> existsTemplate(Consumer<IndexTemplatesExistRequest> consumer) {
IndexTemplatesExistRequest indexTemplatesExistRequest = new IndexTemplatesExistRequest();
consumer.accept(indexTemplatesExistRequest);
return existsTemplate(indexTemplatesExistRequest);
}
/**
* Execute the given {@link IndexTemplatesExistRequest} against the {@literal indices} API.
*
* @param indexTemplatesExistRequest must not be {@literal null}
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
default Mono<Boolean> existsTemplate(IndexTemplatesExistRequest indexTemplatesExistRequest) {
return existsTemplate(HttpHeaders.EMPTY, indexTemplatesExistRequest);
}
/**
* Execute the given {@link IndexTemplatesExistRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param indexTemplatesExistRequest must not be {@literal null}
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
Mono<Boolean> existsTemplate(HttpHeaders headers, IndexTemplatesExistRequest indexTemplatesExistRequest);
/**
* Execute the given {@link DeleteIndexTemplateRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
default Mono<Boolean> deleteTemplate(Consumer<DeleteIndexTemplateRequest> consumer) {
DeleteIndexTemplateRequest deleteIndexTemplateRequest = new DeleteIndexTemplateRequest();
consumer.accept(deleteIndexTemplateRequest);
return deleteTemplate(deleteIndexTemplateRequest);
}
/**
* Execute the given {@link DeleteIndexTemplateRequest} against the {@literal indices} API.
*
* @param deleteIndexTemplateRequest must not be {@literal null}
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
default Mono<Boolean> deleteTemplate(DeleteIndexTemplateRequest deleteIndexTemplateRequest) {
return deleteTemplate(HttpHeaders.EMPTY, deleteIndexTemplateRequest);
}
/**
* Execute the given {@link DeleteIndexTemplateRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param deleteIndexTemplateRequest must not be {@literal null}
* @return the {@link Mono} emitting {@literal true} if the template exists, {@literal false} otherwise.
* @since 4.1
*/
Mono<Boolean> deleteTemplate(HttpHeaders headers, DeleteIndexTemplateRequest deleteIndexTemplateRequest);
}
}

View File

@ -15,6 +15,7 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
@ -27,6 +28,9 @@ import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
import org.springframework.data.elasticsearch.client.util.RequestConverters;
@ -156,7 +160,38 @@ public interface RequestCreator {
return RequestConverters::updateAliases;
}
/**
* @since 4.1
*/
default Function<GetAliasesRequest, Request> getAlias() {
return RequestConverters::getAlias;
}
/**
* @since 4.1
*/
default Function<PutIndexTemplateRequest, Request> putTemplate() {
return RequestConverters::putTemplate;
}
/**
* @since 4.1
*/
default Function<GetIndexTemplatesRequest, Request> getTemplates() {
return RequestConverters::getTemplates;
}
/**
* @since 4.1
*/
default Function<IndexTemplatesExistRequest, Request> templatesExist() {
return RequestConverters::templatesExist;
}
/**
* @since 4.1
*/
default Function<DeleteIndexTemplateRequest, Request> deleteTemplate() {
return RequestConverters::deleteTemplate;
}
}

View File

@ -25,8 +25,11 @@ import java.util.Locale;
import java.util.StringJoiner;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.lucene.util.BytesRef;
@ -47,6 +50,7 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.explain.ExplainRequest;
@ -67,6 +71,9 @@ import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RethrottleRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.AnalyzeRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings;
@ -743,7 +750,9 @@ public class RequestConverters {
public static Request indexRefresh(RefreshRequest refreshRequest) {
String[] indices = refreshRequest.indices() == null ? Strings.EMPTY_ARRAY : refreshRequest.indices();
Request request = new Request(HttpMethod.POST.name(), RequestConverters.endpoint(indices, "_refresh"));
// using a GET here as reactor-netty set the transfer-encoding to chunked on POST requests which blocks on
// Elasticsearch when no body is sent.
Request request = new Request(HttpMethod.GET.name(), RequestConverters.endpoint(indices, "_refresh"));
Params parameters = new Params(request);
parameters.withIndicesOptions(refreshRequest.indicesOptions());
@ -831,6 +840,57 @@ public class RequestConverters {
return request;
}
public static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) {
String endpoint = (new RequestConverters.EndpointBuilder()) //
.addPathPartAsIs("_template") //
.addPathPart(putIndexTemplateRequest.name()) //
.build(); //
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
params.withMasterTimeout(putIndexTemplateRequest.masterNodeTimeout());
if (putIndexTemplateRequest.create()) {
params.putParam("create", Boolean.TRUE.toString());
}
if (Strings.hasText(putIndexTemplateRequest.cause())) {
params.putParam("cause", putIndexTemplateRequest.cause());
}
request.setEntity(
RequestConverters.createEntity(putIndexTemplateRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
return request;
}
public static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) {
final String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_template")
.addCommaSeparatedPathParts(getIndexTemplatesRequest.names()).build();
final Request request = new Request(HttpGet.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
params.withLocal(getIndexTemplatesRequest.isLocal());
params.withMasterTimeout(getIndexTemplatesRequest.getMasterNodeTimeout());
return request;
}
public static Request templatesExist(IndexTemplatesExistRequest indexTemplatesExistRequest) {
final String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_template")
.addCommaSeparatedPathParts(indexTemplatesExistRequest.names()).build();
final Request request = new Request(HttpHead.METHOD_NAME, endpoint);
final RequestConverters.Params params = new RequestConverters.Params(request);
params.withLocal(indexTemplatesExistRequest.isLocal());
params.withMasterTimeout(indexTemplatesExistRequest.getMasterNodeTimeout());
return request;
}
public static Request deleteTemplate(DeleteIndexTemplateRequest deleteIndexTemplateRequest) {
String name = deleteIndexTemplateRequest.name();
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_template").addPathPart(name).build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
params.withMasterTimeout(deleteIndexTemplateRequest.masterNodeTimeout());
return request;
}
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) {
try {

View File

@ -19,15 +19,14 @@ import static org.springframework.util.StringUtils.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
@ -93,21 +92,31 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
Document settings = null;
if (boundClass != null) {
Class<?> clazz = boundClass;
if (clazz.isAnnotationPresent(Setting.class)) {
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
settings = loadSettings(settingPath);
}
if (settings == null) {
settings = getRequiredPersistentEntity(clazz).getDefaultSettings();
}
settings = createSettings(boundClass);
}
return doCreate(getIndexCoordinates(), settings);
}
@Override
public Document createSettings(Class<?> clazz) {
Assert.notNull(clazz, "clazz must not be null");
Document settings = null;
if (clazz.isAnnotationPresent(Setting.class)) {
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
settings = loadSettings(settingPath);
}
if (settings == null) {
settings = getRequiredPersistentEntity(clazz).getDefaultSettings();
}
return settings;
}
@Override
public boolean create(Document settings) {
return doCreate(getIndexCoordinates(), settings);
@ -234,9 +243,15 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
String mapping = new MappingBuilder(elasticsearchConverter).buildPropertyMapping(clazz);
return Document.parse(mapping);
} catch (Exception e) {
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
throw new UncategorizedElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
}
}
@Override
public Document createSettings() {
return createSettings(checkForBoundClass());
}
// endregion
// region Helper functions
@ -246,7 +261,7 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
@Override
public IndexCoordinates getIndexCoordinates() {
return (boundClass != null) ? getIndexCoordinatesFor(boundClass) : boundIndex;
return (boundClass != null) ? getIndexCoordinatesFor(boundClass) : Objects.requireNonNull(boundIndex);
}
public IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
@ -266,27 +281,5 @@ abstract class AbstractDefaultIndexOperations implements IndexOperations {
}
return null;
}
protected Document convertSettingsResponseToMap(GetSettingsResponse response, String indexName) {
Document settings = Document.create();
if (!response.getIndexToDefaultSettings().isEmpty()) {
Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName);
for (String key : defaultSettings.keySet()) {
settings.put(key, defaultSettings.get(key));
}
}
if (!response.getIndexToSettings().isEmpty()) {
Settings customSettings = response.getIndexToSettings().get(indexName);
for (String key : customSettings.keySet()) {
settings.put(key, customSettings.get(key));
}
}
return settings;
}
// endregion
}

View File

@ -16,7 +16,6 @@
package org.springframework.data.elasticsearch.core;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -27,17 +26,27 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.GetMappingsResponse;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.lang.Nullable;
@ -111,7 +120,6 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
GetMappingsResponse mapping = client.indices().getMapping(mappingsRequest, RequestOptions.DEFAULT);
// we only return data for the first index name that was requested (always have done so)
String index1 = mappingsRequest.indices()[0];
Map<String, Object> result = new LinkedHashMap<>();
return mapping.mappings().get(index1).getSourceAsMap();
});
}
@ -174,7 +182,7 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
GetSettingsResponse response = restTemplate.execute(client -> client.indices() //
.getSettings(getSettingsRequest, RequestOptions.DEFAULT));
return convertSettingsResponseToMap(response, getSettingsRequest.indices()[0]);
return requestFactory.fromSettingsResponse(response, getSettingsRequest.indices()[0]);
}
@Override
@ -186,5 +194,53 @@ class DefaultIndexOperations extends AbstractDefaultIndexOperations implements I
restTemplate.execute(client -> client.indices().refresh(refreshRequest, RequestOptions.DEFAULT));
}
@Override
public boolean putTemplate(PutTemplateRequest putTemplateRequest) {
Assert.notNull(putTemplateRequest, "putTemplateRequest must not be null");
PutIndexTemplateRequest putIndexTemplateRequest = requestFactory.putIndexTemplateRequest(putTemplateRequest);
return restTemplate.execute(
client -> client.indices().putTemplate(putIndexTemplateRequest, RequestOptions.DEFAULT).isAcknowledged());
}
@Override
public TemplateData getTemplate(GetTemplateRequest getTemplateRequest) {
Assert.notNull(getTemplateRequest, "getTemplateRequest must not be null");
// getIndexTemplate throws an error on non-existing template names
if (!existsTemplate(new ExistsTemplateRequest(getTemplateRequest.getTemplateName()))) {
return null;
}
GetIndexTemplatesRequest getIndexTemplatesRequest = requestFactory.getIndexTemplatesRequest(getTemplateRequest);
GetIndexTemplatesResponse getIndexTemplatesResponse = restTemplate
.execute(client -> client.indices().getIndexTemplate(getIndexTemplatesRequest, RequestOptions.DEFAULT));
return requestFactory.getTemplateData(getIndexTemplatesResponse, getTemplateRequest.getTemplateName());
}
@Override
public boolean existsTemplate(ExistsTemplateRequest existsTemplateRequest) {
Assert.notNull(existsTemplateRequest, "existsTemplateRequest must not be null");
IndexTemplatesExistRequest putIndexTemplateRequest = requestFactory
.indexTemplatesExistsRequest(existsTemplateRequest);
return restTemplate
.execute(client -> client.indices().existsTemplate(putIndexTemplateRequest, RequestOptions.DEFAULT));
}
@Override
public boolean deleteTemplate(DeleteTemplateRequest deleteTemplateRequest) {
Assert.notNull(deleteTemplateRequest, "deleteTemplateRequest must not be null");
DeleteIndexTemplateRequest deleteIndexTemplateRequest = requestFactory
.deleteIndexTemplateRequest(deleteTemplateRequest);
return restTemplate.execute(
client -> client.indices().deleteTemplate(deleteIndexTemplateRequest, RequestOptions.DEFAULT).isAcknowledged());
}
// endregion
}

View File

@ -30,7 +30,11 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@ -41,7 +45,12 @@ import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverte
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.MappingBuilder;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.lang.Nullable;
@ -90,21 +99,12 @@ class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
public Mono<Boolean> create() {
String indexName = getIndexCoordinates().getIndexName();
Document settings = null;
if (boundClass != null) {
Class<?> clazz = boundClass;
if (clazz.isAnnotationPresent(Setting.class)) {
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
return loadDocument(settingPath, "@Setting").flatMap(document -> doCreate(indexName, document));
}
settings = getRequiredPersistentEntity(clazz).getDefaultSettings();
return createSettings(boundClass).flatMap(settings -> doCreate(indexName, settings));
} else {
return doCreate(indexName, null);
}
return doCreate(indexName, settings);
}
@Override
@ -113,8 +113,8 @@ class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
}
private Mono<Boolean> doCreate(String indexName, @Nullable Document settings) {
CreateIndexRequest request = requestFactory.createIndexRequestReactive(getIndexCoordinates().getIndexName(),
settings);
CreateIndexRequest request = requestFactory.createIndexRequestReactive(indexName, settings);
return Mono.from(operations.executeWithIndicesClient(client -> client.createIndex(request)));
}
@ -189,6 +189,24 @@ class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
// endregion
// region settings
@Override
public Mono<Document> createSettings() {
return createSettings(checkForBoundClass());
}
@Override
public Mono<Document> createSettings(Class<?> clazz) {
if (clazz.isAnnotationPresent(Setting.class)) {
String settingPath = clazz.getAnnotation(Setting.class).settingPath();
return loadDocument(settingPath, "@Setting");
}
return Mono.just(getRequiredPersistentEntity(clazz).getDefaultSettings());
}
@Override
public Mono<Document> getSettings(boolean includeDefaults) {
@ -225,6 +243,55 @@ class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
return Mono.from(operations.executeWithIndicesClient(client -> client.getAliases(getAliasesRequest)))
.map(GetAliasesResponse::getAliases).map(requestFactory::convertAliasesResponse);
}
// endregion
// region templates
@Override
public Mono<Boolean> putTemplate(PutTemplateRequest putTemplateRequest) {
Assert.notNull(putTemplateRequest, "putTemplateRequest must not be null");
PutIndexTemplateRequest putIndexTemplateRequest = requestFactory.putIndexTemplateRequest(putTemplateRequest);
return Mono.from(operations.executeWithIndicesClient(client -> client.putTemplate(putIndexTemplateRequest)));
}
@Override
public Mono<TemplateData> getTemplate(GetTemplateRequest getTemplateRequest) {
Assert.notNull(getTemplateRequest, "getTemplateRequest must not be null");
GetIndexTemplatesRequest getIndexTemplatesRequest = requestFactory.getIndexTemplatesRequest(getTemplateRequest);
return Mono.from(operations.executeWithIndicesClient(client -> client.getTemplate(getIndexTemplatesRequest)))
.flatMap(response -> {
if (response != null) {
TemplateData templateData = requestFactory.getTemplateData(response, getTemplateRequest.getTemplateName());
if (templateData != null) {
return Mono.just(templateData);
}
}
return Mono.empty();
});
}
@Override
public Mono<Boolean> existsTemplate(ExistsTemplateRequest existsTemplateRequest) {
Assert.notNull(existsTemplateRequest, "existsTemplateRequest must not be null");
IndexTemplatesExistRequest indexTemplatesExistRequest = requestFactory
.indexTemplatesExistsRequest(existsTemplateRequest);
return Mono.from(operations.executeWithIndicesClient(client -> client.existsTemplate(indexTemplatesExistRequest)));
}
@Override
public Mono<Boolean> deleteTemplate(DeleteTemplateRequest deleteTemplateRequest) {
Assert.notNull(deleteTemplateRequest, "deleteTemplateRequest must not be null");
DeleteIndexTemplateRequest deleteIndexTemplateRequest = requestFactory
.deleteIndexTemplateRequest(deleteTemplateRequest);
return Mono.from(operations.executeWithIndicesClient(client -> client.deleteTemplate(deleteIndexTemplateRequest)));
}
// endregion

View File

@ -16,6 +16,7 @@
package org.springframework.data.elasticsearch.core;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -32,13 +33,27 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuild
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.cluster.metadata.IndexTemplateMetadata;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.lang.Nullable;
@ -53,6 +68,8 @@ import org.springframework.util.Assert;
*/
class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations implements IndexOperations {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTransportIndexOperations.class);
private final Client client;
public DefaultTransportIndexOperations(Client client, ElasticsearchConverter elasticsearchConverter,
@ -140,7 +157,7 @@ class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations imp
}
@Override
protected Map<String, Set<AliasData>> doGetAliases(String[] aliasNames, String[] indexNames) {
protected Map<String, Set<AliasData>> doGetAliases(@Nullable String[] aliasNames, @Nullable String[] indexNames) {
GetAliasesRequest getAliasesRequest = requestFactory.getAliasesRequest(aliasNames, indexNames);
@ -183,4 +200,89 @@ class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations imp
client.admin().indices().refresh(request).actionGet();
}
@Override
public boolean putTemplate(PutTemplateRequest putTemplateRequest) {
Assert.notNull(putTemplateRequest, "putTemplateRequest must not be null");
PutIndexTemplateRequest putIndexTemplateRequest = requestFactory.putIndexTemplateRequest(client,
putTemplateRequest);
return client.admin().indices().putTemplate(putIndexTemplateRequest).actionGet().isAcknowledged();
}
@Override
public TemplateData getTemplate(GetTemplateRequest getTemplateRequest) {
Assert.notNull(getTemplateRequest, "getTemplateRequest must not be null");
GetIndexTemplatesRequest getIndexTemplatesRequest = requestFactory.getIndexTemplatesRequest(client,
getTemplateRequest);
GetIndexTemplatesResponse getIndexTemplatesResponse = client.admin().indices()
.getTemplates(getIndexTemplatesRequest).actionGet();
for (IndexTemplateMetadata indexTemplateMetadata : getIndexTemplatesResponse.getIndexTemplates()) {
if (indexTemplateMetadata.getName().equals(getTemplateRequest.getTemplateName())) {
Document settings = Document.create();
Settings templateSettings = indexTemplateMetadata.settings();
templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key)));
Map<String, AliasData> aliases = new LinkedHashMap<>();
ImmutableOpenMap<String, AliasMetadata> aliasesResponse = indexTemplateMetadata.aliases();
Iterator<String> keysItAliases = aliasesResponse.keysIt();
while (keysItAliases.hasNext()) {
String key = keysItAliases.next();
aliases.put(key, requestFactory.convertAliasMetadata(aliasesResponse.get(key)));
}
Map<String, String> mappingsDoc = new LinkedHashMap<>();
ImmutableOpenMap<String, CompressedXContent> mappingsResponse = indexTemplateMetadata.mappings();
Iterator<String> keysItMappings = mappingsResponse.keysIt();
while (keysItMappings.hasNext()) {
String key = keysItMappings.next();
mappingsDoc.put(key, mappingsResponse.get(key).string());
}
String mappingsJson = mappingsDoc.get("_doc");
Document mapping = null;
if (mappingsJson != null) {
try {
mapping = Document.from((Map<String, ? extends Object>) Document.parse(mappingsJson).get("_doc"));
} catch (Exception e) {
LOGGER.warn("Got invalid mappings JSON: {}", mappingsJson);
}
}
TemplateData templateData = TemplateData.builder()
.withIndexPatterns(indexTemplateMetadata.patterns().toArray(new String[0])) //
.withSettings(settings) //
.withMapping(mapping) //
.withAliases(aliases) //
.withOrder(indexTemplateMetadata.order()) //
.withVersion(indexTemplateMetadata.version()).build();
return templateData;
}
}
return null;
}
@Override
public boolean existsTemplate(ExistsTemplateRequest existsTemplateRequest) {
Assert.notNull(existsTemplateRequest, "existsTemplateRequest must not be null");
// client.admin().indices() has no method for checking the existence
return getTemplate(new GetTemplateRequest(existsTemplateRequest.getTemplateName())) != null;
}
@Override
public boolean deleteTemplate(DeleteTemplateRequest deleteTemplateRequest) {
Assert.notNull(deleteTemplateRequest, "deleteTemplateRequest must not be null");
DeleteIndexTemplateRequest deleteIndexTemplateRequest = requestFactory.deleteIndexTemplateRequest(client,
deleteTemplateRequest);
return client.admin().indices().deleteTemplate(deleteIndexTemplateRequest).actionGet().isAcknowledged();
}
}

View File

@ -23,8 +23,14 @@ import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.lang.Nullable;
/**
* The operations for the
@ -122,6 +128,23 @@ public interface IndexOperations {
// endregion
// region settings
/**
* Creates the index settings for the entity this IndexOperations is bound to.
*
* @return a settings document.
* @since 4.1
*/
Document createSettings();
/**
* Creates the index settings from the annotations on the given class
*
* @param clazz the class to create the index settings from
* @return a settings document.
* @since 4.1
*/
Document createSettings(Class<?> clazz);
/**
* Get mapping for an index defined by a class.
*
@ -157,7 +180,7 @@ public interface IndexOperations {
boolean addAlias(AliasQuery query);
/**
* Get the alias informations for a specified index.
* Get the alias information for a specified index.
*
* @return alias information
* @deprecated since 4.1, use {@link #getAliases(String...)} or {@link #getAliasesForIndex(String...)}.
@ -203,6 +226,87 @@ public interface IndexOperations {
Map<String, Set<AliasData>> getAliasesForIndex(String... indexNames);
// endregion
// region templates
/**
* Creates an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html).
*
* @param putTemplateRequest template request parameters
* @return true if successful
* @since 4.1
*/
boolean putTemplate(PutTemplateRequest putTemplateRequest);
/**
* gets an index template using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param templateName the template name
* @return TemplateData, {@literal null} if no template with the given name exists.
* @since 4.1
*/
@Nullable
default TemplateData getTemplate(String templateName) {
return getTemplate(new GetTemplateRequest(templateName));
}
/**
* gets an index template using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param getTemplateRequest the request parameters
* @return TemplateData, {@literal null} if no template with the given name exists.
* @since 4.1
*/
@Nullable
TemplateData getTemplate(GetTemplateRequest getTemplateRequest);
/**
* check if an index template exists using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param templateName the template name
* @return {@literal true} if the index exists
* @since 4.1
*/
default boolean existsTemplate(String templateName) {
return existsTemplate(new ExistsTemplateRequest(templateName));
}
/**
* check if an index template exists using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param existsTemplateRequest the request parameters
* @return {@literal true} if the index exists
* @since 4.1
*/
boolean existsTemplate(ExistsTemplateRequest existsTemplateRequest);
/**
* Deletes an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html).
*
* @param templateName the template name
* @return true if successful
* @since 4.1
*/
default boolean deleteTemplate(String templateName) {
return deleteTemplate(new DeleteTemplateRequest(templateName));
}
/**
* Deletes an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html).
*
* @param deleteTemplateRequest template request parameters
* @return true if successful
* @since 4.1
*/
boolean deleteTemplate(DeleteTemplateRequest deleteTemplateRequest);
// endregion
// region helper functions
/**
* get the current {@link IndexCoordinates}. These may change over time when the entity class has a SpEL constructed
@ -212,5 +316,6 @@ public interface IndexOperations {
* @since 4.1
*/
IndexCoordinates getIndexCoordinates();
// endregion
}

View File

@ -23,6 +23,11 @@ import java.util.Set;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
/**
@ -126,6 +131,23 @@ public interface ReactiveIndexOperations {
// endregion
// region settings
/**
* Creates the index settings for the entity this IndexOperations is bound to.
*
* @return a settings document.
* @since 4.1
*/
Mono<Document> createSettings();
/**
* Creates the index settings from the annotations on the given class
*
* @param clazz the class to create the index settings from
* @return a settings document.
* @since 4.1
*/
Mono<Document> createSettings(Class<?> clazz);
/**
* get the settings for the index
*
@ -173,13 +195,92 @@ public interface ReactiveIndexOperations {
Mono<Map<String, Set<AliasData>>> getAliasesForIndex(String... indexNames);
// endregion
// region templates
/**
* Creates an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @param putTemplateRequest template request parameters
* @return Mono of {@literal true} if the template could be stored
* @since 4.1
*/
Mono<Boolean> putTemplate(PutTemplateRequest putTemplateRequest);
/**
* gets an index template using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param templateName the template name
* @return Mono of TemplateData, {@literal Mono.empty()} if no template with the given name exists.
* @since 4.1
*/
default Mono<TemplateData> getTemplate(String templateName) {
return getTemplate(new GetTemplateRequest(templateName));
}
/**
* gets an index template using the legacy Elasticsearch
* interface/Users/peter/Entwicklung/Projekte/spring-data-elasticsearch/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java.
*
* @param getTemplateRequest the request parameters
* @return Mono of TemplateData, {@literal Mono.empty()} if no template with the given name exists.
* @since 4.1
*/
Mono<TemplateData> getTemplate(GetTemplateRequest getTemplateRequest);
/**
* Checks if an index template exists using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @param templateName the template name
* @return Mono of {@literal true} if the template exists
* @since 4.1
*/
default Mono<Boolean> existsTemplate(String templateName) {
return existsTemplate(new ExistsTemplateRequest(templateName));
}
/**
* Checks if an index template exists using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @param existsTemplateRequest template request parameters
* @return Mono of {@literal true} if the template exists
* @since 4.1
*/
Mono<Boolean> existsTemplate(ExistsTemplateRequest existsTemplateRequest);
/**
* Deletes an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @param templateName the template name
* @return Mono of {@literal true} if the template could be deleted
* @since 4.1
*/
default Mono<Boolean> deleteTemplate(String templateName) {
return deleteTemplate(new DeleteTemplateRequest(templateName));
}
/**
* Deletes an index template using the legacy Elasticsearch interface (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @param deleteTemplateRequest template request parameters
* @return Mono of {@literal true} if the template could be deleted
* @since 4.1
*/
Mono<Boolean> deleteTemplate(DeleteTemplateRequest deleteTemplateRequest);
// endregion
// region helper functions
/**
* get the current {@link IndexCoordinates}. These may change over time when the entity class has a SpEL constructed
* index name. When this IndexOperations is not bound to a class, the bound IndexCoordinates are returned.
*
* @return IndexCoordinates
* @ince 4.1
* @since 4.1
*/
IndexCoordinates getIndexCoordinates();

View File

@ -19,14 +19,17 @@ import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.springframework.util.CollectionUtils.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
@ -37,6 +40,7 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuild
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
@ -56,9 +60,15 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.IndexTemplateMetadata;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.settings.Settings;
@ -92,6 +102,11 @@ import org.springframework.data.elasticsearch.core.index.AliasAction;
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
@ -466,8 +481,8 @@ class RequestFactory {
return new GetMappingsRequest().indices(indexNames);
}
public org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest(Client client,
IndexCoordinates index) {
public org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest(
@SuppressWarnings("unused") Client client, IndexCoordinates index) {
String[] indexNames = index.getIndexNames();
return new org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest().indices(indexNames);
@ -477,22 +492,217 @@ class RequestFactory {
Map<String, Set<AliasData>> converted = new LinkedHashMap<>();
aliasesResponse.forEach((index, aliasMetaDataSet) -> {
Set<AliasData> aliasDataSet = new LinkedHashSet<>();
aliasMetaDataSet.forEach(aliasMetaData -> {
Document filter = null;
CompressedXContent aliasMetaDataFilter = aliasMetaData.getFilter();
if (aliasMetaDataFilter != null) {
filter = Document.parse(aliasMetaDataFilter.string());
}
aliasDataSet.add(AliasData.of(aliasMetaData.alias(), filter, aliasMetaData.indexRouting(),
aliasMetaData.getSearchRouting(), aliasMetaData.writeIndex(), aliasMetaData.isHidden()));
});
aliasMetaDataSet.forEach(aliasMetaData -> aliasDataSet.add(convertAliasMetadata(aliasMetaData)));
converted.put(index, aliasDataSet);
});
return converted;
}
public AliasData convertAliasMetadata(AliasMetadata aliasMetaData) {
Document filter = null;
CompressedXContent aliasMetaDataFilter = aliasMetaData.getFilter();
if (aliasMetaDataFilter != null) {
filter = Document.parse(aliasMetaDataFilter.string());
}
AliasData aliasData = AliasData.of(aliasMetaData.alias(), filter, aliasMetaData.indexRouting(),
aliasMetaData.getSearchRouting(), aliasMetaData.writeIndex(), aliasMetaData.isHidden());
return aliasData;
}
public PutIndexTemplateRequest putIndexTemplateRequest(PutTemplateRequest putTemplateRequest) {
PutIndexTemplateRequest request = new PutIndexTemplateRequest(putTemplateRequest.getName())
.patterns(Arrays.asList(putTemplateRequest.getIndexPatterns()));
if (putTemplateRequest.getSettings() != null) {
request.settings(putTemplateRequest.getSettings());
}
if (putTemplateRequest.getMappings() != null) {
request.mapping(putTemplateRequest.getMappings());
}
request.order(putTemplateRequest.getOrder()).version(putTemplateRequest.getVersion());
AliasActions aliasActions = putTemplateRequest.getAliasActions();
if (aliasActions != null) {
aliasActions.getActions().forEach(aliasAction -> {
AliasActionParameters parameters = aliasAction.getParameters();
String[] parametersAliases = parameters.getAliases();
if (parametersAliases != null) {
for (String aliasName : parametersAliases) {
Alias alias = new Alias(aliasName);
if (parameters.getRouting() != null) {
alias.routing(parameters.getRouting());
}
if (parameters.getIndexRouting() != null) {
alias.indexRouting(parameters.getIndexRouting());
}
if (parameters.getSearchRouting() != null) {
alias.searchRouting(parameters.getSearchRouting());
}
if (parameters.getHidden() != null) {
alias.isHidden(parameters.getHidden());
}
if (parameters.getWriteIndex() != null) {
alias.writeIndex(parameters.getWriteIndex());
}
Query filterQuery = parameters.getFilterQuery();
if (filterQuery != null) {
elasticsearchConverter.updateQuery(filterQuery, parameters.getFilterQueryClass());
QueryBuilder queryBuilder = getFilter(filterQuery);
if (queryBuilder == null) {
queryBuilder = getQuery(filterQuery);
}
alias.filter(queryBuilder);
}
request.alias(alias);
}
}
});
}
return request;
}
/**
* The version for the transport client needs a different PutIndexTemplateRequest class
*/
public org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest(
@SuppressWarnings("unused") Client client, PutTemplateRequest putTemplateRequest) {
org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest request = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest(
putTemplateRequest.getName()).patterns(Arrays.asList(putTemplateRequest.getIndexPatterns()));
if (putTemplateRequest.getSettings() != null) {
request.settings(putTemplateRequest.getSettings());
}
if (putTemplateRequest.getMappings() != null) {
request.mapping("_doc", putTemplateRequest.getMappings());
}
request.order(putTemplateRequest.getOrder()).version(putTemplateRequest.getVersion());
AliasActions aliasActions = putTemplateRequest.getAliasActions();
if (aliasActions != null) {
aliasActions.getActions().forEach(aliasAction -> {
AliasActionParameters parameters = aliasAction.getParameters();
String[] parametersAliases = parameters.getAliases();
if (parametersAliases != null) {
for (String aliasName : parametersAliases) {
Alias alias = new Alias(aliasName);
if (parameters.getRouting() != null) {
alias.routing(parameters.getRouting());
}
if (parameters.getIndexRouting() != null) {
alias.indexRouting(parameters.getIndexRouting());
}
if (parameters.getSearchRouting() != null) {
alias.searchRouting(parameters.getSearchRouting());
}
if (parameters.getHidden() != null) {
alias.isHidden(parameters.getHidden());
}
if (parameters.getWriteIndex() != null) {
alias.writeIndex(parameters.getWriteIndex());
}
Query filterQuery = parameters.getFilterQuery();
if (filterQuery != null) {
elasticsearchConverter.updateQuery(filterQuery, parameters.getFilterQueryClass());
QueryBuilder queryBuilder = getFilter(filterQuery);
if (queryBuilder == null) {
queryBuilder = getQuery(filterQuery);
}
alias.filter(queryBuilder);
}
request.alias(alias);
}
}
});
}
return request;
}
public GetIndexTemplatesRequest getIndexTemplatesRequest(GetTemplateRequest getTemplateRequest) {
return new GetIndexTemplatesRequest(getTemplateRequest.getTemplateName());
}
@Nullable
public TemplateData getTemplateData(GetIndexTemplatesResponse getIndexTemplatesResponse, String templateName) {
for (IndexTemplateMetadata indexTemplateMetadata : getIndexTemplatesResponse.getIndexTemplates()) {
if (indexTemplateMetadata.name().equals(templateName)) {
Document settings = Document.create();
Settings templateSettings = indexTemplateMetadata.settings();
templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key)));
Map<String, AliasData> aliases = new LinkedHashMap<>();
ImmutableOpenMap<String, AliasMetadata> aliasesResponse = indexTemplateMetadata.aliases();
Iterator<String> keysIt = aliasesResponse.keysIt();
while (keysIt.hasNext()) {
String key = keysIt.next();
aliases.put(key, convertAliasMetadata(aliasesResponse.get(key)));
}
TemplateData templateData = TemplateData.builder()
.withIndexPatterns(indexTemplateMetadata.patterns().toArray(new String[0])) //
.withSettings(settings) //
.withMapping(Document.from(indexTemplateMetadata.mappings().getSourceAsMap())) //
.withAliases(aliases) //
.withOrder(indexTemplateMetadata.order()) //
.withVersion(indexTemplateMetadata.version()).build();
return templateData;
}
}
return null;
}
public org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest getIndexTemplatesRequest(
Client client, GetTemplateRequest getTemplateRequest) {
return new org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest(
getTemplateRequest.getTemplateName());
}
public IndexTemplatesExistRequest indexTemplatesExistsRequest(ExistsTemplateRequest existsTemplateRequest) {
return new IndexTemplatesExistRequest(existsTemplateRequest.getTemplateName());
}
public DeleteIndexTemplateRequest deleteIndexTemplateRequest(DeleteTemplateRequest deleteTemplateRequest) {
return new DeleteIndexTemplateRequest(deleteTemplateRequest.getTemplateName());
}
public org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest deleteIndexTemplateRequest(
Client client, DeleteTemplateRequest deleteTemplateRequest) {
return new org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest(
deleteTemplateRequest.getTemplateName());
}
// endregion
// region delete
@ -524,10 +734,12 @@ class RequestFactory {
.setRefresh(true);
if (query.isLimiting()) {
// noinspection ConstantConditions
deleteByQueryRequest.setBatchSize(query.getMaxResults());
}
if (query.hasScrollTime()) {
// noinspection ConstantConditions
deleteByQueryRequest.setScroll(TimeValue.timeValueMillis(query.getScrollTime().toMillis()));
}
@ -752,10 +964,7 @@ class RequestFactory {
String indexName = index.getIndexName();
MoreLikeThisQueryBuilder.Item item = new MoreLikeThisQueryBuilder.Item(indexName, query.getId());
String[] fields = null;
if (query.getFields() != null) {
fields = query.getFields().toArray(new String[] {});
}
String[] fields = query.getFields().toArray(new String[] {});
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = QueryBuilders.moreLikeThisQuery(fields, null,
new MoreLikeThisQueryBuilder.Item[] { item });
@ -817,11 +1026,7 @@ class RequestFactory {
QueryBuilder elasticsearchQuery = getQuery(query);
QueryBuilder elasticsearchFilter = getFilter(query);
if (elasticsearchQuery != null) {
searchRequest.source().query(elasticsearchQuery);
} else {
searchRequest.source().query(QueryBuilders.matchAllQuery());
}
searchRequest.source().query(elasticsearchQuery);
if (elasticsearchFilter != null) {
searchRequest.source().postFilter(elasticsearchFilter);
@ -839,11 +1044,7 @@ class RequestFactory {
QueryBuilder elasticsearchQuery = getQuery(query);
QueryBuilder elasticsearchFilter = getFilter(query);
if (elasticsearchQuery != null) {
searchRequestBuilder.setQuery(elasticsearchQuery);
} else {
searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
}
searchRequestBuilder.setQuery(elasticsearchQuery);
if (elasticsearchFilter != null) {
searchRequestBuilder.setPostFilter(elasticsearchFilter);
@ -888,6 +1089,7 @@ class RequestFactory {
}
if (query.isLimiting()) {
// noinspection ConstantConditions
sourceBuilder.size(query.getMaxResults());
}
@ -899,9 +1101,7 @@ class RequestFactory {
request.preference(query.getPreference());
}
if (query.getSearchType() != null) {
request.searchType(query.getSearchType());
}
request.searchType(query.getSearchType());
prepareSort(query, sourceBuilder, getPersistentEntity(clazz));
@ -965,6 +1165,7 @@ class RequestFactory {
}
if (query.isLimiting()) {
// noinspection ConstantConditions
searchRequestBuilder.setSize(query.getMaxResults());
}

View File

@ -20,7 +20,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Value class capturing the arguments for an {@link AliasAction}.  
* Value class capturing the arguments for an {@link AliasAction}.
*
* @author Peter-Josef Meisch
* @since 4.1
@ -54,6 +54,14 @@ public class AliasActionParameters {
return new Builder();
}
/**
* a Builder to create AliasActionParameters to be used when creating index templates. Automatically sets the index
* name to an empty string, as this is not used in templates
*/
public static Builder builderForTemplate() {
return new Builder().withIndices("");
}
public String[] getIndices() {
return indices;
}
@ -158,7 +166,7 @@ public class AliasActionParameters {
public AliasActionParameters build() {
Assert.notNull(indices, "indices must bes set");
Assert.notNull(indices, "indices must be set");
return new AliasActionParameters(indices, aliases, isHidden, isWriteIndex, routing, indexRouting, searchRouting,
filterQuery, filterQueryClass);

View File

@ -0,0 +1,36 @@
/*
* Copyright 2020 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.index;
import org.springframework.util.Assert;
/**
* @author Peter-Josef Meisch
*/
public class DeleteTemplateRequest {
private final String templateName;
public DeleteTemplateRequest(String templateName) {
Assert.notNull(templateName, "templateName must not be null");
this.templateName = templateName;
}
public String getTemplateName() {
return templateName;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2020 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.index;
import org.springframework.util.Assert;
/**
* @author Peter-Josef Meisch
*/
public class ExistsTemplateRequest {
private final String templateName;
public ExistsTemplateRequest(String templateName) {
Assert.notNull(templateName, "templateName must not be null");
this.templateName = templateName;
}
public String getTemplateName() {
return templateName;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2020 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.index;
import org.springframework.util.Assert;
/**
* @author Peter-Josef Meisch
*/
public class GetTemplateRequest {
private final String templateName;
public GetTemplateRequest(String templateName) {
Assert.notNull(templateName, "templateName must not be null");
this.templateName = templateName;
}
public String getTemplateName() {
return templateName;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright 2020 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.index;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Request to create an index template. This is to create legacy templates (@see
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates-v1.html)
*
* @author Peter-Josef Meisch
* @since 4.1
*/
public class PutTemplateRequest {
private final String name;
private final String[] indexPatterns;
@Nullable final private Document settings;
@Nullable final private Document mappings;
@Nullable final AliasActions aliasActions;
private final int order;
@Nullable final Integer version;
private PutTemplateRequest(String name, String[] indexPatterns, @Nullable Document settings,
@Nullable Document mappings, @Nullable AliasActions aliasActions, int order, @Nullable Integer version) {
this.name = name;
this.indexPatterns = indexPatterns;
this.settings = settings;
this.mappings = mappings;
this.aliasActions = aliasActions;
this.order = order;
this.version = version;
}
public String getName() {
return name;
}
public String[] getIndexPatterns() {
return indexPatterns;
}
@Nullable
public Document getSettings() {
return settings;
}
@Nullable
public Document getMappings() {
return mappings;
}
@Nullable
public AliasActions getAliasActions() {
return aliasActions;
}
public int getOrder() {
return order;
}
@Nullable
public Integer getVersion() {
return version;
}
public static TemplateRequestBuilder builder(String name, String... indexPatterns) {
return new TemplateRequestBuilder(name, indexPatterns);
}
public static final class TemplateRequestBuilder {
private final String name;
private final String[] indexPatterns;
@Nullable private Document settings;
@Nullable private Document mappings;
@Nullable AliasActions aliasActions;
private int order = 0;
@Nullable Integer version;
private TemplateRequestBuilder(String name, String... indexPatterns) {
Assert.notNull(name, "name must not be null");
Assert.notNull(indexPatterns, "indexPatterns must not be null");
this.name = name;
this.indexPatterns = indexPatterns;
}
public TemplateRequestBuilder withSettings(Document settings) {
this.settings = settings;
return this;
}
public TemplateRequestBuilder withMappings(Document mappings) {
this.mappings = mappings;
return this;
}
public TemplateRequestBuilder withAliasActions(AliasActions aliasActions) {
aliasActions.getActions().forEach(action -> Assert.isTrue(action instanceof AliasAction.Add,
"only alias add actions are allowed in templates"));
this.aliasActions = aliasActions;
return this;
}
public TemplateRequestBuilder withOrder(int order) {
this.order = order;
return this;
}
public TemplateRequestBuilder withVersion(@Nullable Integer version) {
this.version = version;
return this;
}
public PutTemplateRequest build() {
return new PutTemplateRequest(name, indexPatterns, settings, mappings, aliasActions, order, version);
}
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright 2020 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.index;
import java.util.Map;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.lang.Nullable;
/**
* Data returned for template information retrieval.
*
* @author Peter-Josef Meisch
*/
public class TemplateData {
@Nullable private final String[] indexPatterns;
@Nullable Document settings;
@Nullable Document mapping;
@Nullable private final Map<String, AliasData> aliases;
int order;
@Nullable Integer version;
private TemplateData(@Nullable String[] indexPatterns, @Nullable Document settings, @Nullable Document mapping,
@Nullable Map<String, AliasData> aliases, int order, @Nullable Integer version) {
this.indexPatterns = indexPatterns;
this.settings = settings;
this.mapping = mapping;
this.order = order;
this.version = version;
this.aliases = aliases;
}
public static TemplateDataBuilder builder() {
return new TemplateDataBuilder();
}
@Nullable
public String[] getIndexPatterns() {
return indexPatterns;
}
@Nullable
public Document getSettings() {
return settings;
}
@Nullable
public Document getMapping() {
return mapping;
}
@Nullable
public Map<String, AliasData> getAliases() {
return aliases;
}
public int getOrder() {
return order;
}
@Nullable
public Integer getVersion() {
return version;
}
public static final class TemplateDataBuilder {
@Nullable Document settings;
@Nullable Document mapping;
int order;
@Nullable Integer version;
@Nullable private String[] indexPatterns;
@Nullable private Map<String, AliasData> aliases;
private TemplateDataBuilder() {}
public TemplateDataBuilder withIndexPatterns(String[] indexPatterns) {
this.indexPatterns = indexPatterns;
return this;
}
public TemplateDataBuilder withSettings(Document settings) {
this.settings = settings;
return this;
}
public TemplateDataBuilder withMapping(Document mapping) {
this.mapping = mapping;
return this;
}
public TemplateDataBuilder withOrder(int order) {
this.order = order;
return this;
}
public TemplateDataBuilder withVersion(Integer version) {
this.version = version;
return this;
}
public TemplateDataBuilder withAliases(Map<String, AliasData> aliases) {
this.aliases = aliases;
return this;
}
public TemplateData build() {
return new TemplateData(indexPatterns, settings, mapping, aliases, order, version);
}
}
}

View File

@ -15,17 +15,20 @@
*/
package org.springframework.data.elasticsearch.core.query;
import org.springframework.lang.Nullable;
/**
* SourceFilter implementation for providing includes and excludes.
*
* @Author Jon Tsiros
* @author Jon Tsiros
* @author Peter-Josef Meisch
*/
public class FetchSourceFilter implements SourceFilter {
private final String[] includes;
private final String[] excludes;
@Nullable private final String[] includes;
@Nullable private final String[] excludes;
public FetchSourceFilter(final String[] includes, final String[] excludes) {
public FetchSourceFilter(@Nullable final String[] includes, @Nullable final String[] excludes) {
this.includes = includes;
this.excludes = excludes;
}

View File

@ -34,14 +34,14 @@ import org.springframework.lang.Nullable;
public class MoreLikeThisQuery {
@Nullable private String id;
private List<String> searchIndices = new ArrayList<>();
private List<String> searchTypes = new ArrayList<>();
private List<String> fields = new ArrayList<>();
private final List<String> searchIndices = new ArrayList<>();
private final List<String> searchTypes = new ArrayList<>();
private final List<String> fields = new ArrayList<>();
@Nullable private String routing;
@Nullable private Float percentTermsToMatch;
@Nullable private Integer minTermFreq;
@Nullable private Integer maxQueryTerms;
private List<String> stopWords = new ArrayList<>();
private final List<String> stopWords = new ArrayList<>();
@Nullable private Integer minDocFreq;
@Nullable private Integer maxDocFreq;
@Nullable private Integer minWordLen;

View File

@ -232,7 +232,8 @@ public interface Query {
boolean getTrackTotalHits();
/**
* For queries that are used in delete request, these are internally handled by Elasticsearch as scroll/bulk delete queries.
* For queries that are used in delete request, these are internally handled by Elasticsearch as scroll/bulk delete
* queries. Must not return {@literal null} when {@link #hasScrollTime()} returns {@literal true}.
*
* @return the scrolltime settings
* @since 4.0
@ -241,7 +242,8 @@ public interface Query {
Duration getScrollTime();
/**
* For queries that are used in delete request, these are internally handled by Elasticsearch as scroll/bulk delete queries.
* For queries that are used in delete request, these are internally handled by Elasticsearch as scroll/bulk delete
* queries.
*
* @param scrollTime the scrolltime settings
* @since 4.0

View File

@ -15,14 +15,19 @@
*/
package org.springframework.data.elasticsearch.core.query;
import org.springframework.lang.Nullable;
/**
* SourceFilter for providing includes and excludes.
*
* @Author Jon Tsiros
* @author Jon Tsiros
* @author Peter-Josef Meisch
*/
public interface SourceFilter {
@Nullable
String[] getIncludes();
@Nullable
String[] getExcludes();
}

View File

@ -23,7 +23,9 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.LocalDate;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.json.JSONException;
import org.junit.jupiter.api.AfterEach;
@ -44,10 +46,16 @@ import org.springframework.data.elasticsearch.core.index.AliasAction;
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest;
import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest;
import org.springframework.data.elasticsearch.core.index.GetTemplateRequest;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.index.TemplateData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfiguration;
/**
@ -378,6 +386,128 @@ public class ReactiveIndexOperationsTest {
.verifyComplete();
}
@Test // DATAES-612
void shouldPutTemplate() {
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class)
.block();
org.springframework.data.elasticsearch.core.document.Document settings = indexOps
.createSettings(TemplateClass.class).block();
AliasActions aliasActions = new AliasActions(
new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build()));
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("test-template", "log-*") //
.withSettings(settings) //
.withMappings(mapping) //
.withAliasActions(aliasActions) //
.withOrder(11) //
.withVersion(42) //
.build();
Boolean acknowledged = indexOps.putTemplate(putTemplateRequest).block();
assertThat(acknowledged).isTrue();
}
@Test // DATAES-612
void shouldReturnNullOnNonExistingGetTemplate() {
String templateName = "template" + UUID.randomUUID().toString();
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
GetTemplateRequest getTemplateRequest = new GetTemplateRequest(templateName);
indexOps.getTemplate(getTemplateRequest).as(StepVerifier::create).verifyComplete();
}
@Test // DATAES-612
void shouldGetTemplate() throws JSONException {
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class)
.block();
org.springframework.data.elasticsearch.core.document.Document settings = indexOps
.createSettings(TemplateClass.class).block();
AliasActions aliasActions = new AliasActions(
new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build()));
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("test-template", "log-*") //
.withSettings(settings) //
.withMappings(mapping) //
.withAliasActions(aliasActions) //
.withOrder(11) //
.withVersion(42) //
.build();
Boolean acknowledged = indexOps.putTemplate(putTemplateRequest).block();
assertThat(acknowledged).isTrue();
GetTemplateRequest getTemplateRequest = new GetTemplateRequest(putTemplateRequest.getName());
TemplateData templateData = indexOps.getTemplate(getTemplateRequest).block();
assertThat(templateData).isNotNull();
assertThat(templateData.getIndexPatterns()).containsExactlyInAnyOrder(putTemplateRequest.getIndexPatterns());
assertEquals(settings.toJson(), templateData.getSettings().toJson(), false);
assertEquals(mapping.toJson(), templateData.getMapping().toJson(), false);
Map<String, AliasData> aliases = templateData.getAliases();
assertThat(aliases).hasSize(2);
AliasData alias1 = aliases.get("alias1");
assertThat(alias1.getAlias()).isEqualTo("alias1");
AliasData alias2 = aliases.get("alias2");
assertThat(alias2.getAlias()).isEqualTo("alias2");
assertThat(templateData.getOrder()).isEqualTo(putTemplateRequest.getOrder());
assertThat(templateData.getVersion()).isEqualTo(putTemplateRequest.getVersion());
}
@Test // DATAES-612
void shouldCheckExists() {
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
String templateName = "template" + UUID.randomUUID().toString();
ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest(templateName);
boolean exists = indexOps.existsTemplate(existsTemplateRequest).block();
assertThat(exists).isFalse();
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder(templateName, "log-*") //
.withOrder(11) //
.withVersion(42) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest).block();
assertThat(acknowledged).isTrue();
exists = indexOps.existsTemplate(existsTemplateRequest).block();
assertThat(exists).isTrue();
}
@Test // DATAES-612
void shouldDeleteTemplate() {
ReactiveIndexOperations indexOps = operations.indexOps(Entity.class);
String templateName = "template" + UUID.randomUUID().toString();
ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest(templateName);
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder(templateName, "log-*") //
.withOrder(11) //
.withVersion(42) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest).block();
assertThat(acknowledged).isTrue();
boolean exists = indexOps.existsTemplate(existsTemplateRequest).block();
assertThat(exists).isTrue();
acknowledged = indexOps.deleteTemplate(new DeleteTemplateRequest(templateName)).block();
assertThat(acknowledged).isTrue();
exists = indexOps.existsTemplate(existsTemplateRequest).block();
assertThat(exists).isFalse();
}
@Data
@Document(indexName = TESTINDEX, shards = 3, replicas = 2, refreshInterval = "4s")
static class Entity {
@ -400,4 +530,29 @@ public class ReactiveIndexOperationsTest {
static class EntityWithAnnotatedSettingsAndMappings {
@Id private String id;
}
@Document(indexName = "test-template", shards = 3, replicas = 2, refreshInterval = "5s")
static class TemplateClass {
@Id @Nullable private String id;
@Field(type = FieldType.Text) @Nullable private String message;
@Nullable
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Nullable
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
}

View File

@ -32,6 +32,7 @@ import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
@ -51,6 +52,7 @@ import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.index.AliasAction;
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.PutTemplateRequest;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.Criteria;
@ -371,6 +373,71 @@ class RequestFactoryTests {
assertEquals(expected, json, false);
}
@Test // DATAES-612
void shouldCreatePutIndexTemplateRequest() throws JSONException, IOException {
String expected = "{\n" + //
" \"index_patterns\": [\n" + //
" \"test-*\"\n" + //
" ],\n" + //
" \"order\": 42,\n" + //
" \"version\": 7,\n" + //
" \"settings\": {\n" + //
" \"index\": {\n" + //
" \"number_of_replicas\": \"2\",\n" + //
" \"number_of_shards\": \"3\",\n" + //
" \"refresh_interval\": \"7s\",\n" + //
" \"store\": {\n" + //
" \"type\": \"oops\"\n" + //
" }\n" + //
" }\n" + //
" },\n" + //
" \"mappings\": {\n" + //
" \"properties\": {\n" + //
" \"price\": {\n" + //
" \"type\": \"double\"\n" + //
" }\n" + //
" }\n" + //
" },\n" + //
" \"aliases\":{\n" + //
" \"alias1\": {},\n" + //
" \"alias2\": {},\n" + //
" \"alias3\": {\n" + //
" \"routing\": \"11\"\n" + //
" }\n" + //
" }\n" + //
"}\n"; //
org.springframework.data.elasticsearch.core.document.Document settings = org.springframework.data.elasticsearch.core.document.Document
.create();
settings.put("index.number_of_replicas", 2);
settings.put("index.number_of_shards", 3);
settings.put("index.refresh_interval", "7s");
settings.put("index.store.type", "oops");
org.springframework.data.elasticsearch.core.document.Document mappings = org.springframework.data.elasticsearch.core.document.Document
.parse("{\"properties\":{\"price\":{\"type\":\"double\"}}}");
AliasActions aliasActions = new AliasActions(
new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build()),
new AliasAction.Add(
AliasActionParameters.builderForTemplate().withAliases("alias3").withRouting("11").build()));
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("test-template", "test-*") //
.withSettings(settings) //
.withMappings(mappings) //
.withAliasActions(aliasActions) //
.withOrder(42) //
.withVersion(7) //
.build(); //
PutIndexTemplateRequest putIndexTemplateRequest = requestFactory.putIndexTemplateRequest(putTemplateRequest);
String json = requestToString(putIndexTemplateRequest);
System.out.println(json);
assertEquals(expected, json, false);
}
private String requestToString(ToXContent request) throws IOException {
return XContentHelper.toXContent(request, XContentType.JSON, true).utf8ToString();
}

View File

@ -58,7 +58,7 @@ class ElasticsearchDateConverterTests {
@Test // DATAES-792
void shouldConvertLegacyDateToString() {
GregorianCalendar calendar = GregorianCalendar
.from(ZonedDateTime.of(LocalDateTime.of(2020, 04, 19, 19, 44), ZoneId.of("UTC")));
.from(ZonedDateTime.of(LocalDateTime.of(2020, 4, 19, 19, 44), ZoneId.of("UTC")));
Date legacyDate = calendar.getTime();
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date_time);
@ -70,7 +70,7 @@ class ElasticsearchDateConverterTests {
@Test // DATAES-792
void shouldParseLegacyDateFromString() {
GregorianCalendar calendar = GregorianCalendar
.from(ZonedDateTime.of(LocalDateTime.of(2020, 04, 19, 19, 44), ZoneId.of("UTC")));
.from(ZonedDateTime.of(LocalDateTime.of(2020, 4, 19, 19, 44), ZoneId.of("UTC")));
Date legacyDate = calendar.getTime();
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date_time);

View File

@ -0,0 +1,192 @@
/*
* Copyright 2020 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.index;
import static org.assertj.core.api.Assertions.*;
import static org.skyscreamer.jsonassert.JSONAssert.*;
import java.util.Map;
import java.util.UUID;
import org.json.JSONException;
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.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
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.junit.jupiter.ElasticsearchRestTemplateConfiguration;
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfiguration;
/**
* @author Peter-Josef Meisch
*/
@SpringIntegrationTest
@ContextConfiguration(classes = { ElasticsearchRestTemplateConfiguration.class })
public class TemplateTests {
@Autowired ElasticsearchOperations operations;
@Test // DATAES-612
void shouldCreateTemplate() {
IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care"));
org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class);
org.springframework.data.elasticsearch.core.document.Document settings = indexOps
.createSettings(TemplateClass.class);
AliasActions aliasActions = new AliasActions(
new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build()));
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("test-template", "log-*") //
.withSettings(settings) //
.withMappings(mapping) //
.withAliasActions(aliasActions) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest);
assertThat(acknowledged).isTrue();
}
@Test // DATAES-612
void shouldReturnNullOnNonExistingGetTemplate() {
String templateName = "template" + UUID.randomUUID().toString();
IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care"));
GetTemplateRequest getTemplateRequest = new GetTemplateRequest(templateName);
TemplateData templateData = indexOps.getTemplate(getTemplateRequest);
assertThat(templateData).isNull();
}
@Test // DATAES-612
void shouldGetTemplate() throws JSONException {
IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care"));
org.springframework.data.elasticsearch.core.document.Document mapping = indexOps.createMapping(TemplateClass.class);
org.springframework.data.elasticsearch.core.document.Document settings = indexOps
.createSettings(TemplateClass.class);
AliasActions aliasActions = new AliasActions(
new AliasAction.Add(AliasActionParameters.builderForTemplate().withAliases("alias1", "alias2").build()));
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("test-template", "log-*") //
.withSettings(settings) //
.withMappings(mapping) //
.withAliasActions(aliasActions) //
.withOrder(11) //
.withVersion(42) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest);
assertThat(acknowledged).isTrue();
GetTemplateRequest getTemplateRequest = new GetTemplateRequest(putTemplateRequest.getName());
TemplateData templateData = indexOps.getTemplate(getTemplateRequest);
assertThat(templateData).isNotNull();
assertThat(templateData.getIndexPatterns()).containsExactlyInAnyOrder(putTemplateRequest.getIndexPatterns());
assertEquals(settings.toJson(), templateData.getSettings().toJson(), false);
assertEquals(mapping.toJson(), templateData.getMapping().toJson(), false);
Map<String, AliasData> aliases = templateData.getAliases();
assertThat(aliases).hasSize(2);
AliasData alias1 = aliases.get("alias1");
assertThat(alias1.getAlias()).isEqualTo("alias1");
AliasData alias2 = aliases.get("alias2");
assertThat(alias2.getAlias()).isEqualTo("alias2");
assertThat(templateData.getOrder()).isEqualTo(putTemplateRequest.getOrder());
assertThat(templateData.getVersion()).isEqualTo(putTemplateRequest.getVersion());
}
@Test // DATAES-612
void shouldCheckExists() {
IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care"));
String templateName = "template" + UUID.randomUUID().toString();
ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest(templateName);
boolean exists = indexOps.existsTemplate(existsTemplateRequest);
assertThat(exists).isFalse();
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder(templateName, "log-*") //
.withOrder(11) //
.withVersion(42) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest);
assertThat(acknowledged).isTrue();
exists = indexOps.existsTemplate(existsTemplateRequest);
assertThat(exists).isTrue();
}
@Test // DATAES-612
void shouldDeleteTemplate() {
IndexOperations indexOps = operations.indexOps(IndexCoordinates.of("dont-care"));
String templateName = "template" + UUID.randomUUID().toString();
ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest(templateName);
PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder(templateName, "log-*") //
.withOrder(11) //
.withVersion(42) //
.build();
boolean acknowledged = indexOps.putTemplate(putTemplateRequest);
assertThat(acknowledged).isTrue();
boolean exists = indexOps.existsTemplate(existsTemplateRequest);
assertThat(exists).isTrue();
acknowledged = indexOps.deleteTemplate(new DeleteTemplateRequest(templateName));
assertThat(acknowledged).isTrue();
exists = indexOps.existsTemplate(existsTemplateRequest);
assertThat(exists).isFalse();
}
@Document(indexName = "test-template", shards = 3, replicas = 2, refreshInterval = "5s")
static class TemplateClass {
@Id @Nullable private String id;
@Field(type = FieldType.Text) @Nullable private String message;
@Nullable
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Nullable
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 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.index;
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
import org.springframework.test.context.ContextConfiguration;
/**
* @author Peter-Josef Meisch
*/
@ContextConfiguration(classes = { ElasticsearchTemplateConfiguration.class })
public class TemplateTransportTests extends TemplateTests {}