diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java new file mode 100644 index 000000000..1ea286d54 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractDefaultIndexOperations.java @@ -0,0 +1,171 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import static org.springframework.util.StringUtils.*; + +import java.util.HashMap; +import java.util.Map; + +import org.elasticsearch.common.collect.MapBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.elasticsearch.ElasticsearchException; +import org.springframework.data.elasticsearch.annotations.Mapping; +import org.springframework.data.elasticsearch.annotations.Setting; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.index.MappingBuilder; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.util.StringUtils; + +/** + * Base implementation of {@link IndexOperations} common to Transport and Rest based Implementations of IndexOperations. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +abstract class AbstractDefaultIndexOperations implements IndexOperations { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDefaultIndexOperations.class); + + protected final ElasticsearchConverter elasticsearchConverter; + protected final RequestFactory requestFactory; + + public AbstractDefaultIndexOperations(ElasticsearchConverter elasticsearchConverter) { + this.elasticsearchConverter = elasticsearchConverter; + requestFactory = new RequestFactory(elasticsearchConverter); + } + + // region IndexOperations + @Override + public boolean createIndex(String indexName) { + return createIndex(indexName, null); + } + + @Override + public boolean createIndex(Class clazz) { + + String indexName = getRequiredPersistentEntity(clazz).getIndexCoordinates().getIndexName(); + if (clazz.isAnnotationPresent(Setting.class)) { + String settingPath = clazz.getAnnotation(Setting.class).settingPath(); + + if (hasText(settingPath)) { + String settings = ResourceUtil.readFileFromClasspath(settingPath); + + if (hasText(settings)) { + return createIndex(indexName, settings); + } + } else { + LOGGER.info("settingPath in @Setting has to be defined. Using default instead."); + } + } + return createIndex(indexName, getDefaultSettings(getRequiredPersistentEntity(clazz))); + } + + @Override + public boolean createIndex(Class clazz, Object settings) { + return createIndex(getRequiredPersistentEntity(clazz).getIndexCoordinates().getIndexName(), settings); + } + + @Override + public boolean deleteIndex(Class clazz) { + return deleteIndex(getRequiredPersistentEntity(clazz).getIndexCoordinates().getIndexName()); + } + + @Override + public boolean indexExists(Class clazz) { + return indexExists(getIndexCoordinatesFor(clazz).getIndexName()); + } + + @Override + public Map getMapping(Class clazz) { + return getMapping(getIndexCoordinatesFor(clazz)); + } + + @Override + public boolean putMapping(Class clazz) { + return putMapping(clazz, buildMapping(clazz)); + } + + @Override + public boolean putMapping(Class clazz, Object mapping) { + return putMapping(getIndexCoordinatesFor(clazz), mapping); + } + + @Override + public boolean putMapping(IndexCoordinates index, Class clazz) { + return putMapping(index, buildMapping(clazz)); + } + + @Override + public Map getSetting(Class clazz) { + return getSetting(getRequiredPersistentEntity(clazz).getIndexCoordinates().getIndexName()); + } + + @Override + public void refresh(Class clazz) { + refresh(getIndexCoordinatesFor(clazz)); + } + + protected String buildMapping(Class clazz) { + + // load mapping specified in Mapping annotation if present + if (clazz.isAnnotationPresent(Mapping.class)) { + String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath(); + + if (!StringUtils.isEmpty(mappingPath)) { + String mappings = ResourceUtil.readFileFromClasspath(mappingPath); + + if (!StringUtils.isEmpty(mappings)) { + return mappings; + } + } else { + LOGGER.info("mappingPath in @Mapping has to be defined. Building mappings using @Field"); + } + } + + // build mapping from field annotations + try { + return new MappingBuilder(elasticsearchConverter).buildPropertyMapping(clazz); + } catch (Exception e) { + throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e); + } + } + // endregion + + // region Helper functions + private Map getDefaultSettings(ElasticsearchPersistentEntity persistentEntity) { + + if (persistentEntity.isUseServerConfiguration()) + return new HashMap(); + + return new MapBuilder().put("index.number_of_shards", String.valueOf(persistentEntity.getShards())) + .put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas())) + .put("index.refresh_interval", persistentEntity.getRefreshInterval()) + .put("index.store.type", persistentEntity.getIndexStoreType()).map(); + } + + ElasticsearchPersistentEntity getRequiredPersistentEntity(Class clazz) { + return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz); + } + + public IndexCoordinates getIndexCoordinatesFor(Class clazz) { + return getRequiredPersistentEntity(clazz).getIndexCoordinates(); + } + // endregion + +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java index 5f71bb590..8006dc996 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java @@ -1,7 +1,5 @@ package org.springframework.data.elasticsearch.core; -import static org.springframework.util.StringUtils.*; - import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -14,32 +12,28 @@ import org.elasticsearch.action.search.MultiSearchRequest; import org.elasticsearch.action.search.MultiSearchResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.collect.MapBuilder; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.MoreLikeThisQueryBuilder; +import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.suggest.SuggestBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.data.domain.Page; import org.springframework.data.elasticsearch.ElasticsearchException; -import org.springframework.data.elasticsearch.annotations.Document; -import org.springframework.data.elasticsearch.annotations.Mapping; -import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse; -import org.springframework.data.elasticsearch.core.index.MappingBuilder; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.elasticsearch.core.query.DeleteQuery; import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.Query; +import org.springframework.data.util.CloseableIterator; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * AbstractElasticsearchTemplate @@ -49,22 +43,18 @@ import org.springframework.util.StringUtils; */ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchTemplate.class); - protected ElasticsearchConverter elasticsearchConverter; protected RequestFactory requestFactory; + protected IndexOperations indexOperations; - /** - * @since 4.0 - */ - public RequestFactory getRequestFactory() { - return requestFactory; - } + // region Initialization + protected void initialize(ElasticsearchConverter elasticsearchConverter, IndexOperations indexOperations) { - protected void initialize(ElasticsearchConverter elasticsearchConverter) { Assert.notNull(elasticsearchConverter, "elasticsearchConverter must not be null."); + this.elasticsearchConverter = elasticsearchConverter; - this.requestFactory = new RequestFactory(elasticsearchConverter); + requestFactory = new RequestFactory(elasticsearchConverter); + this.indexOperations = indexOperations; } protected ElasticsearchConverter createElasticsearchConverter() { @@ -76,129 +66,54 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper @Override public void setApplicationContext(ApplicationContext context) throws BeansException { + if (elasticsearchConverter instanceof ApplicationContextAware) { ((ApplicationContextAware) elasticsearchConverter).setApplicationContext(context); } } + // endregion - protected String buildMapping(Class clazz) { - - // load mapping specified in Mapping annotation if present - if (clazz.isAnnotationPresent(Mapping.class)) { - String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath(); - if (!StringUtils.isEmpty(mappingPath)) { - String mappings = ResourceUtil.readFileFromClasspath(mappingPath); - if (!StringUtils.isEmpty(mappings)) { - return mappings; - } - } else { - LOGGER.info("mappingPath in @Mapping has to be defined. Building mappings using @Field"); - } - } - - // build mapping from field annotations - try { - MappingBuilder mappingBuilder = new MappingBuilder(elasticsearchConverter); - return mappingBuilder.buildPropertyMapping(clazz); - } catch (Exception e) { - throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e); - } - } - + // region getter/setter @Override - public boolean createIndex(String indexName) { - return createIndexIfNotCreated(indexName); + public IndexOperations getIndexOperations() { + return indexOperations; } + // endregion - private boolean createIndexIfNotCreated(String indexName) { - return indexExists(indexName) || createIndex(indexName, null); - } - - @Override - public boolean createIndex(Class clazz) { - return createIndexIfNotCreated(clazz); - } - - private boolean createIndexIfNotCreated(Class clazz) { - return indexExists(getPersistentEntityFor(clazz).getIndexName()) || createIndexWithSettings(clazz); - } - - private boolean createIndexWithSettings(Class clazz) { - if (clazz.isAnnotationPresent(Setting.class)) { - String settingPath = clazz.getAnnotation(Setting.class).settingPath(); - if (hasText(settingPath)) { - String settings = ResourceUtil.readFileFromClasspath(settingPath); - if (hasText(settings)) { - return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings); - } - } else { - LOGGER.info("settingPath in @Setting has to be defined. Using default instead."); - } - } - return createIndex(getPersistentEntityFor(clazz).getIndexName(), getDefaultSettings(getPersistentEntityFor(clazz))); - } - - @Override - public boolean createIndex(Class clazz, Object settings) { - return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings); - } - - @Override + // region DocumentOperations public void delete(Query query, Class clazz, IndexCoordinates index) { + Assert.notNull(query, "Query must not be null."); + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(searchRequest.source().query()); + delete(deleteQuery, index); } + // endregion + + // region SearchOperations + @Override + public CloseableIterator stream(Query query, Class clazz, IndexCoordinates index) { + long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); + return StreamQueries.streamResults(startScroll(scrollTimeInMillis, query, clazz, index), + scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz), this::clearScroll); + } @Override public Page moreLikeThis(MoreLikeThisQuery query, Class clazz, IndexCoordinates index) { + Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery"); + MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = requestFactory.moreLikeThisQueryBuilder(query, index); + return queryForPage(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz, index); } - protected static String[] toArray(List values) { - String[] valuesAsArray = new String[values.size()]; - return values.toArray(valuesAsArray); - } - @Override - public ElasticsearchConverter getElasticsearchConverter() { - return elasticsearchConverter; - } - - @Override - public ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) { - Assert.isTrue(clazz.isAnnotationPresent(Document.class), "Unable to identify index name. " + clazz.getSimpleName() - + " is not a Document. Make sure the document class is annotated with @Document(indexName=\"foo\")"); - return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz); - } - - private Map getDefaultSettings(ElasticsearchPersistentEntity persistentEntity) { - - if (persistentEntity.isUseServerConfiguration()) - return new HashMap(); - - return new MapBuilder().put("index.number_of_shards", String.valueOf(persistentEntity.getShards())) - .put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas())) - .put("index.refresh_interval", persistentEntity.getRefreshInterval()) - .put("index.store.type", persistentEntity.getIndexStoreType()).map(); - } - - protected void checkForBulkOperationFailure(BulkResponse bulkResponse) { - if (bulkResponse.hasFailures()) { - Map failedDocuments = new HashMap<>(); - for (BulkItemResponse item : bulkResponse.getItems()) { - if (item.isFailed()) - failedDocuments.put(item.getId(), item.getFailureMessage()); - } - throw new ElasticsearchException( - "Bulk operation has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages [" - + failedDocuments + "]", - failedDocuments); - } + public List queryForList(Query query, Class clazz, IndexCoordinates index) { + return queryForPage(query, clazz, index).getContent(); } @Override @@ -244,34 +159,80 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper return res; } - @Override - public boolean putMapping(Class clazz) { - return putMapping(clazz, buildMapping(clazz)); - } - - @Override - public boolean putMapping(Class clazz, Object mapping) { - return putMapping(getIndexCoordinatesFor(clazz), mapping); - } - - @Override - public boolean putMapping(IndexCoordinates index, Class clazz) { - return putMapping(index, buildMapping(clazz)); - } - abstract protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request); + protected List extractIds(SearchResponse response) { + List ids = new ArrayList<>(); + for (SearchHit hit : response.getHits()) { + if (hit != null) { + ids.add(hit.getId()); + } + } + return ids; + } + + // endregion + + // region Helper methods + @Override + public ElasticsearchConverter getElasticsearchConverter() { + return elasticsearchConverter; + } + + /** + * @since 4.0 + */ + public RequestFactory getRequestFactory() { + return requestFactory; + } + + protected static String[] toArray(List values) { + String[] valuesAsArray = new String[values.size()]; + return values.toArray(valuesAsArray); + } + + @Override public abstract SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index); + /** + * @param clazz + * @return the IndexCoordinates defined on the entity. + * @since 4.0 + */ + @Override + public IndexCoordinates getIndexCoordinatesFor(Class clazz) { + return getRequiredPersistentEntity(clazz).getIndexCoordinates(); + } + + protected void checkForBulkOperationFailure(BulkResponse bulkResponse) { + + if (bulkResponse.hasFailures()) { + Map failedDocuments = new HashMap<>(); + for (BulkItemResponse item : bulkResponse.getItems()) { + + if (item.isFailed()) + failedDocuments.put(item.getId(), item.getFailureMessage()); + } + throw new ElasticsearchException( + "Bulk operation has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages [" + + failedDocuments + ']', + failedDocuments); + } + } + protected void setPersistentEntityId(Object entity, String id) { - ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(entity.getClass()); + ElasticsearchPersistentEntity persistentEntity = getRequiredPersistentEntity(entity.getClass()); ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); - // Only deal with text because ES generated Ids are strings ! - + // Only deal with text because ES generated Ids are strings! if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) { persistentEntity.getPropertyAccessor(entity).setProperty(idProperty, id); } } + + ElasticsearchPersistentEntity getRequiredPersistentEntity(Class clazz) { + return elasticsearchConverter.getMappingContext().getRequiredPersistentEntity(clazz); + } + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java new file mode 100644 index 000000000..6b4f1aa03 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultIndexOperations.java @@ -0,0 +1,281 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import static org.elasticsearch.client.Requests.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.http.util.EntityUtils; +import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.indices.GetIndexRequest; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.DeprecationHandler; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentType; +import org.springframework.data.elasticsearch.ElasticsearchException; +import org.springframework.data.elasticsearch.core.client.support.AliasData; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.AliasQuery; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * {@link IndexOperations} implementation using the RestClient. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +class DefaultIndexOperations extends AbstractDefaultIndexOperations implements IndexOperations { + + private RestHighLevelClient client; + + public DefaultIndexOperations(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) { + super(elasticsearchConverter); + this.client = client; + } + + @Override + public boolean createIndex(String indexName, Object settings) { + CreateIndexRequest request = requestFactory.createIndexRequest(indexName, settings); + try { + return client.indices().create(request, RequestOptions.DEFAULT).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Error for creating index: " + request.toString(), e); + } + } + + @Override + public boolean deleteIndex(String indexName) { + + Assert.notNull(indexName, "No index defined for delete operation"); + + if (indexExists(indexName)) { + DeleteIndexRequest request = new DeleteIndexRequest(indexName); + try { + return client.indices().delete(request, RequestOptions.DEFAULT).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Error while deleting index request: " + request.toString(), e); + } + } + return false; + } + + @Override + public boolean indexExists(String indexName) { + GetIndexRequest request = new GetIndexRequest(indexName); + try { + return client.indices().exists(request, RequestOptions.DEFAULT); + } catch (IOException e) { + throw new ElasticsearchException("Error while for indexExists request: " + request.toString(), e); + } + } + + @Override + public boolean putMapping(IndexCoordinates index, Object mapping) { + + Assert.notNull(index, "No index defined for putMapping()"); + + PutMappingRequest request = requestFactory.putMappingRequest(index, mapping); + try { + return client.indices().putMapping(request, RequestOptions.DEFAULT).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("Failed to put mapping for " + index.getIndexName(), e); + } + } + + @Override + public Map getMapping(IndexCoordinates index) { + + Assert.notNull(index, "No index defined for getMapping()"); + + RestClient restClient = client.getLowLevelClient(); + try { + Request request = new Request("GET", + '/' + index.getIndexName() + "/_mapping/" + index.getTypeName() + "?include_type_name=true"); + Response response = restClient.performRequest(request); + return convertMappingResponse(EntityUtils.toString(response.getEntity()), index.getTypeName()); + } catch (Exception e) { + throw new ElasticsearchException("Error while getting mapping for indexName : " + index.getIndexName() + + " type : " + index.getTypeName() + ' ', e); + } + } + + @Override + public boolean addAlias(AliasQuery query, IndexCoordinates index) { + IndicesAliasesRequest request = requestFactory.indicesAddAliasesRequest(query, index); + try { + return client.indices().updateAliases(request, RequestOptions.DEFAULT).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException("failed to update aliases with request: " + request, e); + } + } + + @Override + public boolean removeAlias(AliasQuery query, IndexCoordinates index) { + + Assert.notNull(index, "No index defined for Alias"); + Assert.notNull(query.getAliasName(), "No alias defined"); + + IndicesAliasesRequest indicesAliasesRequest = requestFactory.indicesRemoveAliasesRequest(query, index); + try { + return client.indices().updateAliases(indicesAliasesRequest, RequestOptions.DEFAULT).isAcknowledged(); + } catch (IOException e) { + throw new ElasticsearchException( + "failed to update aliases with indicesRemoveAliasesRequest: " + indicesAliasesRequest, e); + } + } + + @Override + public List queryForAlias(String indexName) { + List aliases = null; + RestClient restClient = client.getLowLevelClient(); + Response response; + String aliasResponse; + + try { + response = restClient.performRequest(new Request("GET", '/' + indexName + "/_alias/*")); + aliasResponse = EntityUtils.toString(response.getEntity()); + } catch (Exception e) { + throw new ElasticsearchException("Error while getting mapping for indexName : " + indexName, e); + } + + return convertAliasResponse(aliasResponse); + } + + @Override + public Map getSetting(String indexName) { + + Assert.notNull(indexName, "No index defined for getSettings"); + + ObjectMapper objMapper = new ObjectMapper(); + Map settings = null; + RestClient restClient = client.getLowLevelClient(); + try { + Response response = restClient.performRequest(new Request("GET", "/" + indexName + "/_settings")); + settings = convertSettingResponse(EntityUtils.toString(response.getEntity()), indexName); + + } catch (Exception e) { + throw new ElasticsearchException("Error while getting settings for indexName : " + indexName, e); + } + return settings; + } + + @Override + public void refresh(IndexCoordinates index) { + + Assert.notNull(index, "No index defined for refresh()"); + + try { + client.indices().refresh(refreshRequest(index.getIndexNames()), RequestOptions.DEFAULT); + } catch (IOException e) { + throw new ElasticsearchException("failed to refresh index: " + index, e); + } + } + + // region Helper methods + private Map convertMappingResponse(String mappingResponse, String type) { + ObjectMapper mapper = new ObjectMapper(); + + try { + Map result = null; + JsonNode node = mapper.readTree(mappingResponse); + + node = node.findValue("mappings").findValue(type); + result = mapper.readValue(mapper.writeValueAsString(node), HashMap.class); + + return result; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + mappingResponse, e); + } + } + + /** + * It takes two steps to create a List from the elasticsearch http response because the aliases field + * is actually a Map by alias name, but the alias name is on the AliasMetadata. + * + * @param aliasResponse + * @return + */ + private List convertAliasResponse(String aliasResponse) { + ObjectMapper mapper = new ObjectMapper(); + + try { + JsonNode node = mapper.readTree(aliasResponse); + node = node.findValue("aliases"); + + if (node == null) { + return Collections.emptyList(); + } + + Map aliasData = mapper.readValue(mapper.writeValueAsString(node), + new TypeReference>() {}); + + Iterable> aliasIter = aliasData.entrySet(); + List aliasMetaDataList = new ArrayList(); + + for (Map.Entry aliasentry : aliasIter) { + AliasData data = aliasentry.getValue(); + aliasMetaDataList.add(AliasMetaData.newAliasMetaDataBuilder(aliasentry.getKey()).filter(data.getFilter()) + .routing(data.getRouting()).searchRouting(data.getSearch_routing()).indexRouting(data.getIndex_routing()) + .build()); + } + return aliasMetaDataList; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + aliasResponse, e); + } + } + + private Map convertSettingResponse(String settingResponse, String indexName) { + ObjectMapper mapper = new ObjectMapper(); + + try { + Settings settings = Settings.fromXContent(XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, settingResponse)); + String prefix = indexName + ".settings."; + // Backwards compatibility. TODO Change to return Settings object. + Map result = new HashMap(); + Set keySet = settings.keySet(); + for (String key : keySet) { + result.put(key.substring(prefix.length()), settings.get(key)); + } + return result; + } catch (IOException e) { + throw new ElasticsearchException("Could not map alias response : " + settingResponse, e); + } + + } + // endregion +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java new file mode 100644 index 000000000..6dc69bd59 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultTransportIndexOperations.java @@ -0,0 +1,141 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import static org.elasticsearch.client.Requests.*; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; +import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder; +import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.common.settings.Settings; +import org.springframework.data.elasticsearch.ElasticsearchException; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.AliasQuery; +import org.springframework.util.Assert; + +/** + * {@link IndexOperations} implementation using the TransportClient. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +class DefaultTransportIndexOperations extends AbstractDefaultIndexOperations implements IndexOperations { + + private final Client client; + + public DefaultTransportIndexOperations(Client client, ElasticsearchConverter elasticsearchConverter) { + super(elasticsearchConverter); + this.client = client; + } + + @Override + public boolean createIndex(String indexName, Object settings) { + CreateIndexRequestBuilder createIndexRequestBuilder = requestFactory.createIndexRequestBuilder(client, indexName, + settings); + return createIndexRequestBuilder.execute().actionGet().isAcknowledged(); + } + + @Override + public boolean deleteIndex(String indexName) { + + Assert.notNull(indexName, "No index defined for delete operation"); + + if (indexExists(indexName)) { + return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged(); + } + return false; + } + + @Override + public boolean indexExists(String indexName) { + return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists(); + } + + @Override + public boolean putMapping(IndexCoordinates index, Object mapping) { + + Assert.notNull(index, "No index defined for putMapping()"); + + PutMappingRequestBuilder requestBuilder = requestFactory.putMappingRequestBuilder(client, index, mapping); + return requestBuilder.execute().actionGet().isAcknowledged(); + } + + @Override + public Map getMapping(IndexCoordinates index) { + + Assert.notNull(index, "No index defined for putMapping()"); + + try { + return client.admin().indices() + .getMappings(new GetMappingsRequest().indices(index.getIndexNames()).types(index.getTypeNames())).actionGet() + .getMappings().get(index.getIndexName()).get(index.getTypeName()).getSourceAsMap(); + } catch (Exception e) { + throw new ElasticsearchException("Error while getting mapping for indexName : " + index.getIndexName() + + " type : " + index.getTypeName() + ' ' + e.getMessage()); + } + } + + @Override + public boolean addAlias(AliasQuery query, IndexCoordinates index) { + IndicesAliasesRequest.AliasActions aliasAction = requestFactory.aliasAction(query, index); + return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged(); + } + + @Override + public boolean removeAlias(AliasQuery query, IndexCoordinates index) { + + Assert.notNull(index, "No index defined for Alias"); + Assert.notNull(query.getAliasName(), "No alias defined"); + + return client.admin().indices().prepareAliases().removeAlias(index.getIndexName(), query.getAliasName()).execute() + .actionGet().isAcknowledged(); + } + + @Override + public List queryForAlias(String indexName) { + return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName)).actionGet().getAliases() + .get(indexName); + } + + @Override + public Map getSetting(String indexName) { + + Assert.notNull(indexName, "No index defined for getSettings"); + + Settings settings = client.admin().indices().getSettings(new GetSettingsRequest()).actionGet().getIndexToSettings() + .get(indexName); + return settings.keySet().stream().collect(Collectors.toMap((key) -> key, (key) -> settings.get(key))); + } + + @Override + public void refresh(IndexCoordinates index) { + + Assert.notNull(index, "No index defined for refresh()"); + + client.admin().indices().refresh(refreshRequest(index.getIndexNames())).actionGet(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java new file mode 100644 index 000000000..58b5ee836 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java @@ -0,0 +1,136 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import java.util.List; + +import org.elasticsearch.action.update.UpdateResponse; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.BulkOptions; +import org.springframework.data.elasticsearch.core.query.DeleteQuery; +import org.springframework.data.elasticsearch.core.query.GetQuery; +import org.springframework.data.elasticsearch.core.query.IndexQuery; +import org.springframework.data.elasticsearch.core.query.Query; +import org.springframework.data.elasticsearch.core.query.UpdateQuery; + +/** + * The operations for the + * Elasticsearch Document APIs. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +public interface DocumentOperations { + + /** + * Index an object. Will do save or update. + * + * @param query the query defining the object + * @param index the index from which the object is read. + * @return returns the document id + */ + String index(IndexQuery query, IndexCoordinates index); + + /** + * Retrieves an object from an index. + * + * @param query the query defining the id of the object to get + * @param clazz the type of the object to be returned + * @param index the index from which the object is read. + * @return the found object + */ + T get(GetQuery query, Class clazz, IndexCoordinates index); + + /** + * Execute a multiGet against elasticsearch for the given ids. + * + * @param query the query defining the ids of the objects to get + * @param clazz the type of the object to be returned + * @param index the index(es) from which the objects are read. + * @return list of objects + */ + List multiGet(Query query, Class clazz, IndexCoordinates index); + + /** + * Bulk index all objects. Will do save or update. + * + * @param queries the queries to execute in bulk + */ + default void bulkIndex(List queries, IndexCoordinates index) { + bulkIndex(queries, BulkOptions.defaultOptions(), index); + } + + /** + * Bulk index all objects. Will do save or update. + * + * @param queries the queries to execute in bulk + * @param bulkOptions options to be added to the bulk request + */ + void bulkIndex(List queries, BulkOptions bulkOptions, IndexCoordinates index); + + /** + * Bulk update all objects. Will do update. + * + * @param queries the queries to execute in bulk + */ + default void bulkUpdate(List queries, IndexCoordinates index) { + bulkUpdate(queries, BulkOptions.defaultOptions(), index); + } + + /** + * Bulk update all objects. Will do update. + * + * @param queries the queries to execute in bulk + * @param bulkOptions options to be added to the bulk request + */ + void bulkUpdate(List queries, BulkOptions bulkOptions, IndexCoordinates index); + + /** + * Delete the one object with provided id. + * + * @param id the document ot delete + * @param index the index from which to delete + * @return documentId of the document deleted + */ + String delete(String id, IndexCoordinates index); + + /** + * Delete all records matching the query. + * + * @param query query defining the objects + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @param index the index from which to delete + */ + void delete(Query query, Class clazz, IndexCoordinates index); + + /** + * Delete all records matching the query. + * + * @param query query defining the objects + * @param index the index where to delete the records + */ + void delete(DeleteQuery query, IndexCoordinates index); + + /** + * Partial update of the document. + * + * @param updateQuery query defining the update + * @param index the index where to update the records + * @return the update response + */ + UpdateResponse update(UpdateQuery updateQuery, IndexCoordinates index); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java index ef467a408..f968f1e3c 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java @@ -17,27 +17,17 @@ package org.springframework.data.elasticsearch.core; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.cluster.metadata.AliasMetaData; -import org.springframework.data.domain.Page; -import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.AliasQuery; -import org.springframework.data.elasticsearch.core.query.BulkOptions; -import org.springframework.data.elasticsearch.core.query.DeleteQuery; -import org.springframework.data.elasticsearch.core.query.GetQuery; -import org.springframework.data.elasticsearch.core.query.IndexQuery; -import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery; -import org.springframework.data.elasticsearch.core.query.Query; -import org.springframework.data.elasticsearch.core.query.UpdateQuery; -import org.springframework.data.util.CloseableIterator; -import org.springframework.lang.Nullable; /** - * ElasticsearchOperations + * ElasticsearchOperations. Since 4.0 this interface only contains common helper functions, the other methods have been + * moved to the different interfaces that are extended by ElasticsearchOperations. The interfaces now reflect the - * @return - */ - Page moreLikeThis(MoreLikeThisQuery query, Class clazz, IndexCoordinates index); - - ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz); - - /** - * @return Converter in use - */ ElasticsearchConverter getElasticsearchConverter(); + IndexCoordinates getIndexCoordinatesFor(Class clazz); + + // region IndexOperations /** - * @param clazz - * @return the IndexCoordinates defined on the entity. - * @since 4.0 + * Create an index for given indexName if it does not already exist. + * + * @param indexName the name of the index + * @return {@literal true} if the index was created + * @deprecated since 4.0, use {@link IndexOperations#createIndex(String) instead} */ - default IndexCoordinates getIndexCoordinatesFor(Class clazz) { - ElasticsearchPersistentEntity entity = getPersistentEntityFor(clazz); - return IndexCoordinates.of(entity.getIndexName()).withTypes(entity.getIndexType()); + @Deprecated + default boolean createIndex(String indexName) { + return getIndexOperations().createIndex(indexName); } + /** + * Create an index for given indexName and Settings. + * + * @param indexName the name of the index + * @param settings the index settings + * @return {@literal true} if the index was created + * @deprecated since 4.0, use {@link IndexOperations#createIndex(String, Object)} instead} + */ + @Deprecated + default boolean createIndex(String indexName, Object settings) { + return getIndexOperations().createIndex(indexName, settings); + } + + /** + * Create an index for a class if it does not already exist. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index was created + * @deprecated since 4.0, use {@link IndexOperations#createIndex(Class)} instead} + */ + @Deprecated + default boolean createIndex(Class clazz) { + return getIndexOperations().createIndex(clazz); + } + + /** + * Create an index for given class and Settings. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @param settings the index settings + * @return {@literal true} if the index was created + * @deprecated since 4.0, use {@link IndexOperations#createIndex(Class, Object)} instead} + */ + @Deprecated + default boolean createIndex(Class clazz, Object settings) { + return getIndexOperations().createIndex(clazz, settings); + } + + /** + * Deletes an index for given entity. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index was deleted + * @deprecated since 4.0, use {@link IndexOperations#deleteIndex(Class)} instead} + */ + @Deprecated + default boolean deleteIndex(Class clazz) { + return getIndexOperations().deleteIndex(clazz); + } + + /** + * Deletes an index. + * + * @param indexName the name of the index to delete + * @return {@literal true} if the index was deleted + * @deprecated since 4.0, use {@link IndexOperations#deleteIndex(String)} instead} + */ + @Deprecated + default boolean deleteIndex(String indexName) { + return getIndexOperations().deleteIndex(indexName); + } + + /** + * check if index exists. + * + * @param indexName the name of the index + * @return {@literal true} if the index exists + * @deprecated since 4.0, use {@link IndexOperations#indexExists(String)} instead} + */ + @Deprecated + default boolean indexExists(String indexName) { + return getIndexOperations().indexExists(indexName); + } + + /** + * check if index is exists. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index exists + * @deprecated since 4.0, use {@link IndexOperations#indexExists(Class)} instead} + */ + @Deprecated + default boolean indexExists(Class clazz) { + return getIndexOperations().indexExists(clazz); + } + + /** + * Create mapping for a class and store it to the index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the mapping could be stored + * @deprecated since 4.0, use {@link IndexOperations#putMapping(Class)} instead} + */ + @Deprecated + default boolean putMapping(Class clazz) { + return getIndexOperations().putMapping(clazz); + } + + /** + * Create mapping for the given class and put the mapping to the given index. + * + * @param index the index to store the mapping to + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the mapping could be stored + * @deprecated since 4.0, use {@link IndexOperations#putMapping(IndexCoordinates, Class)} instead} + */ + @Deprecated + default boolean putMapping(IndexCoordinates index, Class clazz) { + return getIndexOperations().putMapping(index, clazz); + } + + /** + * Stores a mapping to an index. + * + * @param index the index to store the mapping to + * @param mappings can be a JSON String or a {@link Map} + * @return {@literal true} if the mapping could be stored + * @deprecated since 4.0, use {@link IndexOperations#putMapping(IndexCoordinates, Object)} instead} + */ + @Deprecated + default boolean putMapping(IndexCoordinates index, Object mappings) { + return getIndexOperations().putMapping(index, mappings); + } + + /** + * Create mapping for a class Stores a mapping to an index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @param mappings can be a JSON String or a {@link Map} + * @return {@literal true} if the mapping could be stored + * @deprecated since 4.0, use {@link IndexOperations#putMapping(Class, Object)} instead} + */ + @Deprecated + default boolean putMapping(Class clazz, Object mappings) { + return getIndexOperations().putMapping(clazz, mappings); + } + + /** + * Get mapping for an index defined by a class. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document}. + * @return the mapping + * @deprecated since 4.0, use {@link IndexOperations#getMapping(Class)} instead} + */ + @Deprecated + default Map getMapping(Class clazz) { + return getIndexOperations().getMapping(clazz); + } + + /** + * Get mapping for a given index. + * + * @param index the index to read the mapping from + * @return the mapping + * @deprecated since 4.0, use {@link IndexOperations#getMapping(IndexCoordinates)} instead} + */ + @Deprecated + default Map getMapping(IndexCoordinates index) { + return getIndexOperations().getMapping(index); + } + + /** + * Add an alias. + * + * @param query query defining the alias + * @param index the index for which to add an alias + * @return true if the alias was created + * @deprecated since 4.0, use {@link IndexOperations#addAlias(AliasQuery, IndexCoordinates)} instead} + */ + @Deprecated + default boolean addAlias(AliasQuery query, IndexCoordinates index) { + return getIndexOperations().addAlias(query, index); + } + + /** + * Remove an alias. + * + * @param query query defining the alias + * @param index the index for which to remove an alias + * @return true if the alias was removed + * @deprecated since 4.0, use {@link IndexOperations#removeAlias(AliasQuery, IndexCoordinates)} instead} + */ + @Deprecated + default boolean removeAlias(AliasQuery query, IndexCoordinates index) { + return getIndexOperations().removeAlias(query, index); + } + + /** + * Get the alias informations for a specified index. + * + * @param indexName the name of the index + * @return alias information + * @deprecated since 4.0, use {@link IndexOperations#queryForAlias(String)} instead} + */ + @Deprecated + default List queryForAlias(String indexName) { + return getIndexOperations().queryForAlias(indexName); + } + + /** + * Get settings for a given indexName. + * + * @param indexName the name of the index + * @return the settings + * @deprecated since 4.0, use {@link IndexOperations#getSetting(String)} )} instead} + */ + @Deprecated + default Map getSetting(String indexName) { + return getIndexOperations().getSetting(indexName); + } + + /** + * Get settings for a given class. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return the settings + * @deprecated since 4.0, use {@link IndexOperations#getSetting(Class)} instead} + */ + @Deprecated + default Map getSetting(Class clazz) { + return getIndexOperations().getSetting(clazz); + } + + /** + * Refresh the index(es). + * + * @param index the index to refresh + * @deprecated since 4.0, use {@link IndexOperations#refresh(IndexCoordinates)} instead} + */ + @Deprecated + default void refresh(IndexCoordinates index) { + getIndexOperations().refresh(index); + } + + /** + * Refresh the index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @deprecated since 4.0, use {@link IndexOperations#refresh(Class)} instead} + */ + @Deprecated + default void refresh(Class clazz) { + getIndexOperations().refresh(clazz); + } + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java index 6b37bb967..275b49492 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java @@ -15,21 +15,9 @@ */ package org.springframework.data.elasticsearch.core; -import static org.elasticsearch.client.Requests.*; - import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.http.util.EntityUtils; -import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; -import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.get.GetRequest; @@ -45,41 +33,29 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; -import org.elasticsearch.client.Request; import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.indices.GetIndexRequest; -import org.elasticsearch.cluster.metadata.AliasMetaData; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.DeprecationHandler; -import org.elasticsearch.common.xcontent.NamedXContentRegistry; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.reindex.DeleteByQueryRequest; -import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.suggest.SuggestBuilder; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.ElasticsearchException; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; -import org.springframework.data.elasticsearch.core.client.support.AliasData; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.DocumentAdapters; import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse; -import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.BulkOptions; +import org.springframework.data.elasticsearch.core.query.DeleteQuery; +import org.springframework.data.elasticsearch.core.query.GetQuery; +import org.springframework.data.elasticsearch.core.query.IndexQuery; +import org.springframework.data.elasticsearch.core.query.Query; +import org.springframework.data.elasticsearch.core.query.UpdateQuery; import org.springframework.data.elasticsearch.support.SearchHitsUtil; -import org.springframework.data.util.CloseableIterator; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * ElasticsearchRestTemplate * @@ -116,6 +92,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { private RestHighLevelClient client; + // region Initialization public ElasticsearchRestTemplate(RestHighLevelClient client) { initialize(client, createElasticsearchConverter()); } @@ -127,192 +104,11 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { private void initialize(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) { Assert.notNull(client, "Client must not be null!"); this.client = client; - initialize(elasticsearchConverter); - } - - @Override - public boolean addAlias(AliasQuery query, IndexCoordinates index) { - IndicesAliasesRequest request = requestFactory.indicesAddAliasesRequest(query, index); - try { - return client.indices().updateAliases(request, RequestOptions.DEFAULT).isAcknowledged(); - } catch (IOException e) { - throw new ElasticsearchException("failed to update aliases with request: " + request, e); - } - } - - @Override - public boolean removeAlias(AliasQuery query, IndexCoordinates index) { - Assert.notNull(index, "No index defined for Alias"); - Assert.notNull(query.getAliasName(), "No alias defined"); - - IndicesAliasesRequest indicesAliasesRequest = requestFactory.indicesRemoveAliasesRequest(query, index); - try { - return client.indices().updateAliases(indicesAliasesRequest, RequestOptions.DEFAULT).isAcknowledged(); - } catch (IOException e) { - throw new ElasticsearchException("failed to update aliases with indicesRemoveAliasesRequest: " + indicesAliasesRequest, e); - } - } - - @Override - public boolean createIndex(String indexName, Object settings) { - CreateIndexRequest request = requestFactory.createIndexRequest(indexName, settings); - try { - return client.indices().create(request, RequestOptions.DEFAULT).isAcknowledged(); - } catch (IOException e) { - throw new ElasticsearchException("Error for creating index: " + request.toString(), e); - } - } - - @Override - public boolean putMapping(IndexCoordinates index, Object mapping) { - Assert.notNull(index, "No index defined for putMapping()"); - PutMappingRequest request = requestFactory.putMappingRequest(index, mapping); - try { - return client.indices().putMapping(request, RequestOptions.DEFAULT).isAcknowledged(); - } catch (IOException e) { - throw new ElasticsearchException("Failed to put mapping for " + index.getIndexName(), e); - } - } - - @Override - public Map getMapping(IndexCoordinates index) { - Assert.notNull(index, "No index defined for getMapping()"); - RestClient restClient = client.getLowLevelClient(); - try { - Request request = new Request("GET", - '/' + index.getIndexName() + "/_mapping/" + index.getTypeName() + "?include_type_name=true"); - Response response = restClient.performRequest(request); - return convertMappingResponse(EntityUtils.toString(response.getEntity()), index.getTypeName()); - } catch (Exception e) { - throw new ElasticsearchException("Error while getting mapping for indexName : " + index.getIndexName() - + " type : " + index.getTypeName() + ' ', e); - } - } - - private Map convertMappingResponse(String mappingResponse, String type) { - ObjectMapper mapper = new ObjectMapper(); - - try { - Map result = null; - JsonNode node = mapper.readTree(mappingResponse); - - node = node.findValue("mappings").findValue(type); - result = mapper.readValue(mapper.writeValueAsString(node), HashMap.class); - - return result; - } catch (IOException e) { - throw new ElasticsearchException("Could not map alias response : " + mappingResponse, e); - } - - } - - @Override - public T get(GetQuery query, Class clazz, IndexCoordinates index) { - GetRequest request = requestFactory.getRequest(query, index); - try { - GetResponse response = client.get(request, RequestOptions.DEFAULT); - return elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz); - } catch (IOException e) { - throw new ElasticsearchException("Error while getting for request: " + request.toString(), e); - } - } - - @Nullable - private T getObjectFromPage(Page page) { - int contentSize = page.getContent().size(); - Assert.isTrue(contentSize < 2, "Expected 1 but found " + contentSize + " results"); - return contentSize > 0 ? page.getContent().get(0) : null; - } - - @Override - protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request) { - MultiSearchResponse response; - try { - response = client.multiSearch(request, RequestOptions.DEFAULT); - } catch (IOException e) { - throw new ElasticsearchException("Error for search request: " + request.toString(), e); - } - MultiSearchResponse.Item[] items = response.getResponses(); - Assert.isTrue(items.length == request.requests().size(), "Response should has same length with queries"); - return items; - } - - @Override - public AggregatedPage queryForPage(Query query, Class clazz, IndexCoordinates index) { - SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); - SearchResponse response; - try { - response = client.search(searchRequest, RequestOptions.DEFAULT); - } catch (IOException e) { - throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); - } - return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable()); - } - - @Override - public T query(Query query, ResultsExtractor resultsExtractor, @Nullable Class clazz, IndexCoordinates index) { - SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); - try { - SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); - return resultsExtractor.extract(result); - } catch (IOException e) { - throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); - } - } - - @Override - public List queryForList(Query query, Class clazz, IndexCoordinates index) { - return queryForPage(query, clazz, index).getContent(); - } - - @Override - public List queryForIds(Query query, Class clazz, IndexCoordinates index) { - SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); - try { - SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); - return extractIds(response); - } catch (IOException e) { - throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); - } - } - - @Override - public CloseableIterator stream(Query query, Class clazz, IndexCoordinates index) { - long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); - return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, index), clazz); - } - - private CloseableIterator doStream(long scrollTimeInMillis, ScrolledPage page, Class clazz) { - return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz), - this::clearScroll); - } - - @Override - public long count(Query query, Class clazz, IndexCoordinates index) { - Assert.notNull(index, "index must not be null"); - SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); - searchRequest.source().size(0); - - try { - return SearchHitsUtil.getTotalCount(client.search(searchRequest, RequestOptions.DEFAULT).getHits()); - } catch (IOException e) { - throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); - } - } - - @Override - public List multiGet(Query query, Class clazz, IndexCoordinates index) { - Assert.notNull(index, "index must not be null"); - Assert.notEmpty(query.getIds(), "No Id define for Query"); - MultiGetRequest request = requestFactory.multiGetRequest(query, index); - try { - MultiGetResponse result = client.mget(request, RequestOptions.DEFAULT); - return elasticsearchConverter.mapDocuments(DocumentAdapters.from(result), clazz); - } catch (IOException e) { - throw new ElasticsearchException("Error while multiget for request: " + request.toString(), e); - } + initialize(elasticsearchConverter, new DefaultIndexOperations(client, elasticsearchConverter)); } + // endregion + // region DocumentOperations @Override public String index(IndexQuery query, IndexCoordinates index) { IndexRequest request = requestFactory.indexRequest(query, index); @@ -330,17 +126,34 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } @Override - public UpdateResponse update(UpdateQuery query, IndexCoordinates index) { - UpdateRequest request = requestFactory.updateRequest(query, index); + public T get(GetQuery query, Class clazz, IndexCoordinates index) { + GetRequest request = requestFactory.getRequest(query, index); try { - return client.update(request, RequestOptions.DEFAULT); + GetResponse response = client.get(request, RequestOptions.DEFAULT); + return elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz); } catch (IOException e) { - throw new ElasticsearchException("Error while update for request: " + request.toString(), e); + throw new ElasticsearchException("Error while getting for request: " + request.toString(), e); + } + } + + @Override + public List multiGet(Query query, Class clazz, IndexCoordinates index) { + + Assert.notNull(index, "index must not be null"); + Assert.notEmpty(query.getIds(), "No Id define for Query"); + + MultiGetRequest request = requestFactory.multiGetRequest(query, index); + try { + MultiGetResponse result = client.mget(request, RequestOptions.DEFAULT); + return elasticsearchConverter.mapDocuments(DocumentAdapters.from(result), clazz); + } catch (IOException e) { + throw new ElasticsearchException("Error while multiget for request: " + request.toString(), e); } } @Override public void bulkIndex(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + Assert.notNull(queries, "List of IndexQuery must not be null"); Assert.notNull(bulkOptions, "BulkOptions must not be null"); @@ -349,48 +162,16 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { @Override public void bulkUpdate(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + Assert.notNull(queries, "List of UpdateQuery must not be null"); Assert.notNull(bulkOptions, "BulkOptions must not be null"); doBulkOperation(queries, bulkOptions, index); } - private void doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { - BulkRequest bulkRequest = requestFactory.bulkRequest(queries, bulkOptions, index); - try { - checkForBulkOperationFailure(client.bulk(bulkRequest, RequestOptions.DEFAULT)); - } catch (IOException e) { - throw new ElasticsearchException("Error while bulk for request: " + bulkRequest.toString(), e); - } - } - - @Override - public boolean indexExists(String indexName) { - GetIndexRequest request = new GetIndexRequest(indexName); - try { - return client.indices().exists(request, RequestOptions.DEFAULT); - } catch (IOException e) { - throw new ElasticsearchException("Error while for indexExists request: " + request.toString(), e); - } - } - - @Override - public boolean deleteIndex(String indexName) { - Assert.notNull(indexName, "No index defined for delete operation"); - if (indexExists(indexName)) { - DeleteIndexRequest request = new DeleteIndexRequest(indexName); - try { - return client.indices().delete(request, RequestOptions.DEFAULT).isAcknowledged(); - } catch (IOException e) { - throw new ElasticsearchException("Error while deleting index request: " + request.toString(), e); - } - } - return false; - } - @Override public String delete(String id, IndexCoordinates index) { - DeleteRequest request = new DeleteRequest(index.getIndexName(), index.getTypeName(), id); + DeleteRequest request = new DeleteRequest(index.getIndexName(), id); try { return client.delete(request, RequestOptions.DEFAULT).getId(); } catch (IOException e) { @@ -408,9 +189,82 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } } + @Override + public UpdateResponse update(UpdateQuery query, IndexCoordinates index) { + UpdateRequest request = requestFactory.updateRequest(query, index); + try { + return client.update(request, RequestOptions.DEFAULT); + } catch (IOException e) { + throw new ElasticsearchException("Error while update for request: " + request.toString(), e); + } + } + + private void doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + BulkRequest bulkRequest = requestFactory.bulkRequest(queries, bulkOptions, index); + try { + checkForBulkOperationFailure(client.bulk(bulkRequest, RequestOptions.DEFAULT)); + } catch (IOException e) { + throw new ElasticsearchException("Error while bulk for request: " + bulkRequest.toString(), e); + } + } + // endregion + + // region SearchOperations + @Override + public long count(Query query, Class clazz, IndexCoordinates index) { + + Assert.notNull(index, "index must not be null"); + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); + + searchRequest.source().size(0); + + try { + return SearchHitsUtil.getTotalCount(client.search(searchRequest, RequestOptions.DEFAULT).getHits()); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); + } + } + + @Override + public T query(Query query, ResultsExtractor resultsExtractor, @Nullable Class clazz, + IndexCoordinates index) { + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); + try { + SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); + return resultsExtractor.extract(result); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); + } + } + + @Override + public AggregatedPage queryForPage(Query query, Class clazz, IndexCoordinates index) { + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); + SearchResponse response; + try { + response = client.search(searchRequest, RequestOptions.DEFAULT); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); + } + return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable()); + } + + @Override + public List queryForIds(Query query, Class clazz, IndexCoordinates index) { + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); + try { + SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); + return extractIds(response); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + searchRequest.toString(), e); + } + } + @Override public ScrolledPage startScroll(long scrollTimeInMillis, Query query, Class clazz, IndexCoordinates index) { + Assert.notNull(query.getPageable(), "Query.pageable is required for scan & scroll"); + SearchRequest searchRequest = requestFactory.searchRequest(query, clazz, index); searchRequest.scroll(TimeValue.timeValueMillis(scrollTimeInMillis)); @@ -422,7 +276,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } } - @Override public ScrolledPage continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz) { SearchScrollRequest request = new SearchScrollRequest(scrollId); request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis)); @@ -447,119 +300,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } @Override - public Map getSetting(Class clazz) { - return getSetting(getPersistentEntityFor(clazz).getIndexName()); - } - - @Override // TODO change interface to return Settings. - public Map getSetting(String indexName) { - Assert.notNull(indexName, "No index defined for getSettings"); - ObjectMapper objMapper = new ObjectMapper(); - Map settings = null; - RestClient restClient = client.getLowLevelClient(); - try { - Response response = restClient.performRequest(new Request("GET", "/" + indexName + "/_settings")); - settings = convertSettingResponse(EntityUtils.toString(response.getEntity()), indexName); - - } catch (Exception e) { - throw new ElasticsearchException("Error while getting settings for indexName : " + indexName, e); - } - return settings; - } - - private Map convertSettingResponse(String settingResponse, String indexName) { - ObjectMapper mapper = new ObjectMapper(); - - try { - Settings settings = Settings.fromXContent(XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - DeprecationHandler.THROW_UNSUPPORTED_OPERATION, settingResponse)); - String prefix = indexName + ".settings."; - // Backwards compatibility. TODO Change to return Settings object. - Map result = new HashMap(); - Set keySet = settings.keySet(); - for (String key : keySet) { - result.put(key.substring(prefix.length()), settings.get(key)); - } - return result; - } catch (IOException e) { - throw new ElasticsearchException("Could not map alias response : " + settingResponse, e); - } - - } - - @Override - public void refresh(IndexCoordinates index) { - Assert.notNull(index, "No index defined for refresh()"); - try { - client.indices().refresh(refreshRequest(index.getIndexNames()), RequestOptions.DEFAULT); - } catch (IOException e) { - throw new ElasticsearchException("failed to refresh index: " + index, e); - } - } - - @Override - public List queryForAlias(String indexName) { - List aliases = null; - RestClient restClient = client.getLowLevelClient(); - Response response; - String aliasResponse; - - try { - response = restClient.performRequest(new Request("GET", '/' + indexName + "/_alias/*")); - aliasResponse = EntityUtils.toString(response.getEntity()); - } catch (Exception e) { - throw new ElasticsearchException("Error while getting mapping for indexName : " + indexName, e); - } - - return convertAliasResponse(aliasResponse); - } - - /** - * It takes two steps to create a List from the elasticsearch http response because the aliases field - * is actually a Map by alias name, but the alias name is on the AliasMetadata. - * - * @param aliasResponse - * @return - */ - private List convertAliasResponse(String aliasResponse) { - ObjectMapper mapper = new ObjectMapper(); - - try { - JsonNode node = mapper.readTree(aliasResponse); - node = node.findValue("aliases"); - - if (node == null) { - return Collections.emptyList(); - } - - Map aliasData = mapper.readValue(mapper.writeValueAsString(node), - new TypeReference>() {}); - - Iterable> aliasIter = aliasData.entrySet(); - List aliasMetaDataList = new ArrayList(); - - for (Map.Entry aliasentry : aliasIter) { - AliasData data = aliasentry.getValue(); - aliasMetaDataList.add(AliasMetaData.newAliasMetaDataBuilder(aliasentry.getKey()).filter(data.getFilter()) - .routing(data.getRouting()).searchRouting(data.getSearch_routing()).indexRouting(data.getIndex_routing()) - .build()); - } - return aliasMetaDataList; - } catch (IOException e) { - throw new ElasticsearchException("Could not map alias response : " + aliasResponse, e); - } - } - - private List extractIds(SearchResponse response) { - List ids = new ArrayList<>(); - for (SearchHit hit : response.getHits()) { - if (hit != null) { - ids.add(hit.getId()); - } - } - return ids; - } - public SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index) { SearchRequest searchRequest = new SearchRequest(index.getIndexNames()); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); @@ -571,5 +311,20 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } catch (IOException e) { throw new ElasticsearchException("Could not execute search request : " + searchRequest.toString(), e); } + } + + @Override + protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request) { + MultiSearchResponse response; + try { + response = client.multiSearch(request, RequestOptions.DEFAULT); + } catch (IOException e) { + throw new ElasticsearchException("Error for search request: " + request.toString(), e); + } + MultiSearchResponse.Item[] items = response.getResponses(); + Assert.isTrue(items.length == request.requests().size(), "Response should has same length with queries"); + return items; + } + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 7a8ddade5..65a384cd8 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -15,21 +15,9 @@ */ package org.springframework.data.elasticsearch.core; -import static org.elasticsearch.client.Requests.*; - -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.elasticsearch.action.ActionFuture; -import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; -import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; -import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; -import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; -import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder; -import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.get.GetRequestBuilder; import org.elasticsearch.action.get.GetResponse; @@ -42,23 +30,16 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.update.UpdateRequestBuilder; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.Client; -import org.elasticsearch.cluster.metadata.AliasMetaData; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.suggest.SuggestBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.ElasticsearchException; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.DocumentAdapters; import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse; -import org.springframework.data.elasticsearch.core.query.AliasQuery; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.BulkOptions; import org.springframework.data.elasticsearch.core.query.DeleteQuery; import org.springframework.data.elasticsearch.core.query.GetQuery; @@ -66,7 +47,6 @@ import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.core.query.UpdateQuery; import org.springframework.data.elasticsearch.support.SearchHitsUtil; -import org.springframework.data.util.CloseableIterator; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -100,13 +80,13 @@ import org.springframework.util.Assert; */ @Deprecated public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { - private static final Logger QUERY_LOGGER = LoggerFactory .getLogger("org.springframework.data.elasticsearch.core.QUERY"); private Client client; private String searchTimeout; + // region Initialization public ElasticsearchTemplate(Client client) { initialize(client, createElasticsearchConverter()); } @@ -118,132 +98,21 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { private void initialize(Client client, ElasticsearchConverter elasticsearchConverter) { Assert.notNull(client, "Client must not be null!"); this.client = client; - initialize(elasticsearchConverter); + initialize(elasticsearchConverter, new DefaultTransportIndexOperations(client, elasticsearchConverter)); + } + // endregion + + // region getter/setter + public String getSearchTimeout() { + return searchTimeout; } public void setSearchTimeout(String searchTimeout) { this.searchTimeout = searchTimeout; } + // endregion - @Override - public boolean addAlias(AliasQuery query, IndexCoordinates index) { - IndicesAliasesRequest.AliasActions aliasAction = requestFactory.aliasAction(query, index); - return client.admin().indices().prepareAliases().addAliasAction(aliasAction).execute().actionGet().isAcknowledged(); - } - - @Override - public boolean removeAlias(AliasQuery query, IndexCoordinates index) { - Assert.notNull(index, "No index defined for Alias"); - Assert.notNull(query.getAliasName(), "No alias defined"); - return client.admin().indices().prepareAliases().removeAlias(index.getIndexName(), query.getAliasName()).execute() - .actionGet().isAcknowledged(); - } - - @Override - public boolean createIndex(String indexName, Object settings) { - CreateIndexRequestBuilder createIndexRequestBuilder = requestFactory.createIndexRequestBuilder(client, indexName, - settings); - return createIndexRequestBuilder.execute().actionGet().isAcknowledged(); - } - - @Override - public boolean putMapping(IndexCoordinates index, Object mapping) { - Assert.notNull(index, "No index defined for putMapping()"); - PutMappingRequestBuilder requestBuilder = requestFactory.putMappingRequestBuilder(client, index, mapping); - return requestBuilder.execute().actionGet().isAcknowledged(); - } - - @Override - public Map getMapping(IndexCoordinates index) { - Assert.notNull(index, "No index defined for putMapping()"); - try { - return client.admin().indices() - .getMappings(new GetMappingsRequest().indices(index.getIndexNames()).types(index.getTypeNames())).actionGet() - .getMappings().get(index.getIndexName()).get(index.getTypeName()).getSourceAsMap(); - } catch (Exception e) { - throw new ElasticsearchException("Error while getting mapping for indexName : " + index.getIndexName() - + " type : " + index.getTypeName() + ' ' + e.getMessage()); - } - } - - @Override - public T get(GetQuery query, Class clazz, IndexCoordinates index) { - GetRequestBuilder getRequestBuilder = requestFactory.getRequestBuilder(client, query, index); - GetResponse response = getRequestBuilder.execute().actionGet(); - T entity = elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz); - return entity; - } - - @Nullable - private T getObjectFromPage(Page page) { - int contentSize = page.getContent().size(); - Assert.isTrue(contentSize < 2, "Expected 1 but found " + contentSize + " results"); - return contentSize > 0 ? page.getContent().get(0) : null; - } - - @Override - protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request) { - ActionFuture future = client.multiSearch(request); - MultiSearchResponse response = future.actionGet(); - MultiSearchResponse.Item[] items = response.getResponses(); - Assert.isTrue(items.length == request.requests().size(), "Response should have same length with queries"); - return items; - } - - @Override - public T query(Query query, ResultsExtractor resultsExtractor, Class clazz, IndexCoordinates index) { - SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); - SearchResponse response = getSearchResponse(searchRequestBuilder); - return resultsExtractor.extract(response); - } - - @Override - public List queryForList(Query query, Class clazz, IndexCoordinates index) { - return queryForPage(query, clazz, index).getContent(); - } - - @Override - public List queryForIds(Query query, Class clazz, IndexCoordinates index) { - SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); - SearchResponse response = getSearchResponse(searchRequestBuilder); - return extractIds(response); - } - - @Override - public AggregatedPage queryForPage(Query query, Class clazz, IndexCoordinates index) { - SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); - SearchResponse response = getSearchResponse(searchRequestBuilder); - return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable()); - } - - @Override - public CloseableIterator stream(Query query, Class clazz, IndexCoordinates index) { - long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); - return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, index), clazz); - } - - private CloseableIterator doStream(long scrollTimeInMillis, ScrolledPage page, Class clazz) { - return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz), - this::clearScroll); - } - - @Override - public long count(Query query, @Nullable Class clazz, IndexCoordinates index) { - Assert.notNull(index, "index must not be null"); - SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); - searchRequestBuilder.setSize(0); - - return SearchHitsUtil.getTotalCount(getSearchResponse(searchRequestBuilder).getHits()); - } - - @Override - public List multiGet(Query query, Class clazz, IndexCoordinates index) { - Assert.notNull(index, "index must not be null"); - Assert.notEmpty(query.getIds(), "No Id define for Query"); - MultiGetRequestBuilder builder = requestFactory.multiGetRequestBuilder(client, query, index); - return elasticsearchConverter.mapDocuments(DocumentAdapters.from(builder.execute().actionGet()), clazz); - } - + // region DocumentOperations @Override public String index(IndexQuery query, IndexCoordinates index) { IndexRequestBuilder indexRequestBuilder = requestFactory.indexRequestBuilder(client, query, index); @@ -256,13 +125,27 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { } @Override - public UpdateResponse update(UpdateQuery query, IndexCoordinates index) { - UpdateRequestBuilder updateRequestBuilder = requestFactory.updateRequestBuilderFor(client, query, index); - return updateRequestBuilder.execute().actionGet(); + public T get(GetQuery query, Class clazz, IndexCoordinates index) { + GetRequestBuilder getRequestBuilder = requestFactory.getRequestBuilder(client, query, index); + GetResponse response = getRequestBuilder.execute().actionGet(); + T entity = elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz); + return entity; + } + + @Override + public List multiGet(Query query, Class clazz, IndexCoordinates index) { + + Assert.notNull(index, "index must not be null"); + Assert.notEmpty(query.getIds(), "No Id define for Query"); + + MultiGetRequestBuilder builder = requestFactory.multiGetRequestBuilder(client, query, index); + + return elasticsearchConverter.mapDocuments(DocumentAdapters.from(builder.execute().actionGet()), clazz); } @Override public void bulkIndex(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + Assert.notNull(queries, "List of IndexQuery must not be null"); Assert.notNull(bulkOptions, "BulkOptions must not be null"); @@ -271,31 +154,13 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { @Override public void bulkUpdate(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + Assert.notNull(queries, "List of UpdateQuery must not be null"); Assert.notNull(bulkOptions, "BulkOptions must not be null"); doBulkOperation(queries, bulkOptions, index); } - private void doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { - BulkRequestBuilder bulkRequest = requestFactory.bulkRequestBuilder(client, queries, bulkOptions, index); - checkForBulkOperationFailure(bulkRequest.execute().actionGet()); - } - - @Override - public boolean indexExists(String indexName) { - return client.admin().indices().exists(indicesExistsRequest(indexName)).actionGet().isExists(); - } - - @Override - public boolean deleteIndex(String indexName) { - Assert.notNull(indexName, "No index defined for delete operation"); - if (indexExists(indexName)) { - return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged(); - } - return false; - } - @Override public String delete(String id, IndexCoordinates index) { return client.prepareDelete(index.getIndexName(), index.getTypeName(), id).execute().actionGet().getId(); @@ -306,9 +171,55 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { requestFactory.deleteByQueryRequestBuilder(client, deleteQuery, index).get(); } + @Override + public UpdateResponse update(UpdateQuery query, IndexCoordinates index) { + UpdateRequestBuilder updateRequestBuilder = requestFactory.updateRequestBuilderFor(client, query, index); + return updateRequestBuilder.execute().actionGet(); + } + + private void doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { + BulkRequestBuilder bulkRequest = requestFactory.bulkRequestBuilder(client, queries, bulkOptions, index); + checkForBulkOperationFailure(bulkRequest.execute().actionGet()); + } + // endregion + + // region SearchOperations + @Override + public long count(Query query, @Nullable Class clazz, IndexCoordinates index) { + + Assert.notNull(index, "index must not be null"); + + SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); + searchRequestBuilder.setSize(0); + + return SearchHitsUtil.getTotalCount(getSearchResponse(searchRequestBuilder).getHits()); + } + + @Override + public T query(Query query, ResultsExtractor resultsExtractor, Class clazz, IndexCoordinates index) { + SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); + SearchResponse response = getSearchResponse(searchRequestBuilder); + return resultsExtractor.extract(response); + } + + @Override + public AggregatedPage queryForPage(Query query, Class clazz, IndexCoordinates index) { + SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); + SearchResponse response = getSearchResponse(searchRequestBuilder); + return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable()); + } + + @Override + public List queryForIds(Query query, Class clazz, IndexCoordinates index) { + SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); + SearchResponse response = getSearchResponse(searchRequestBuilder); + return extractIds(response); + } + @Override public ScrolledPage startScroll(long scrollTimeInMillis, Query query, Class clazz, IndexCoordinates index) { Assert.notNull(query.getPageable(), "Query.pageable is required for scan & scroll"); + SearchRequestBuilder searchRequestBuilder = requestFactory.searchRequestBuilder(client, query, clazz, index); searchRequestBuilder.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)); SearchResponse response = getSearchResponse(searchRequestBuilder); @@ -327,6 +238,20 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { client.prepareClearScroll().addScrollId(scrollId).execute().actionGet(); } + @Override + public SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index) { + return client.prepareSearch(index.getIndexNames()).suggest(suggestion).get(); + } + + @Override + protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request) { + ActionFuture future = client.multiSearch(request); + MultiSearchResponse response = future.actionGet(); + MultiSearchResponse.Item[] items = response.getResponses(); + Assert.isTrue(items.length == request.requests().size(), "Response should have same length with queries"); + return items; + } + private SearchResponse getSearchResponse(SearchRequestBuilder requestBuilder) { if (QUERY_LOGGER.isDebugEnabled()) { @@ -338,44 +263,5 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { private SearchResponse getSearchResponseWithTimeout(ActionFuture response) { return searchTimeout == null ? response.actionGet() : response.actionGet(searchTimeout); } - - @Override - public Map getSetting(Class clazz) { - return getSetting(getPersistentEntityFor(clazz).getIndexName()); - } - - @Override - public Map getSetting(String indexName) { - Assert.notNull(indexName, "No index defined for getSettings"); - Settings settings = client.admin().indices().getSettings(new GetSettingsRequest()).actionGet().getIndexToSettings() - .get(indexName); - return settings.keySet().stream().collect(Collectors.toMap((key) -> key, (key) -> settings.get(key))); - } - - @Override - public void refresh(IndexCoordinates index) { - Assert.notNull(index, "No index defined for refresh()"); - client.admin().indices().refresh(refreshRequest(index.getIndexNames())).actionGet(); - } - - @Override - public List queryForAlias(String indexName) { - return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName)).actionGet().getAliases() - .get(indexName); - } - - private List extractIds(SearchResponse response) { - List ids = new ArrayList<>(); - for (SearchHit hit : response.getHits()) { - if (hit != null) { - ids.add(hit.getId()); - } - } - return ids; - } - - public SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index) { - return client.prepareSearch(index.getIndexNames()).suggest(suggestion).get(); - } - + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/EntityOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/EntityOperations.java index f1aebbfc2..f376ac270 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/EntityOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/EntityOperations.java @@ -24,6 +24,7 @@ import java.util.Map; import org.springframework.core.convert.ConversionService; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.context.MappingContext; @@ -127,7 +128,7 @@ class EntityOperations { if (StringUtils.isEmpty(index)) { Assert.notNull(entity, "Cannot determine index name"); - return entity.getIndexName(); + return entity.getIndexCoordinates().getIndexName(); } return index; @@ -137,7 +138,7 @@ class EntityOperations { if (StringUtils.isEmpty(type)) { Assert.notNull(entity, "Cannot determine index type"); - return entity.getIndexType(); + return entity.getIndexCoordinates().getTypeName(); } return type; diff --git a/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java new file mode 100644 index 000000000..52e195fae --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/IndexOperations.java @@ -0,0 +1,216 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import java.util.List; +import java.util.Map; + +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.AliasQuery; + +/** + * The operations for the + * Elasticsearch Index APIs. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +public interface IndexOperations { + + /** + * Create an index for given indexName. + * + * @param indexName the name of the index + * @return {@literal true} if the index was created + */ + boolean createIndex(String indexName); + + /** + * Create an index for given indexName and Settings. + * + * @param indexName the name of the index + * @param settings the index settings + * @return {@literal true} if the index was created + */ + boolean createIndex(String indexName, Object settings); + + /** + * Create an index for a class. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index was created + */ + boolean createIndex(Class clazz); + + /** + * Create an index for given class and Settings. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @param settings the index settings + * @return {@literal true} if the index was created + */ + boolean createIndex(Class clazz, Object settings); + + /** + * Deletes an index for given entity. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index was deleted + */ + boolean deleteIndex(Class clazz); + + /** + * Deletes an index. + * + * @param indexName the name of the index to delete + * @return {@literal true} if the index was deleted + */ + boolean deleteIndex(String indexName); + + /** + * check if index exists. + * + * @param indexName the name of the index + * @return {@literal true} if the index exists + */ + boolean indexExists(String indexName); + + /** + * check if index is exists. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the index exists + */ + boolean indexExists(Class clazz); + + /** + * Create mapping for a class and store it to the index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the mapping could be stored + */ + boolean putMapping(Class clazz); + + /** + * Create mapping for the given class and put the mapping to the given index. + * + * @param index the index to store the mapping to + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return {@literal true} if the mapping could be stored + */ + boolean putMapping(IndexCoordinates index, Class clazz); + + /** + * Stores a mapping to an index. + * + * @param index the index to store the mapping to + * @param mappings can be a JSON String or a {@link Map} + * @return {@literal true} if the mapping could be stored + */ + boolean putMapping(IndexCoordinates index, Object mappings); + + /** + * Create mapping for a class Stores a mapping to an index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @param mappings can be a JSON String or a {@link Map} + * @return {@literal true} if the mapping could be stored + */ + boolean putMapping(Class clazz, Object mappings); + + /** + * Get mapping for an index defined by a class. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document}. + * @return the mapping + */ + Map getMapping(Class clazz); + + /** + * Get mapping for a given index. + * + * @param index the index to read the mapping from + * @return the mapping + */ + Map getMapping(IndexCoordinates index); + + /** + * Add an alias. + * + * @param query query defining the alias + * @param index the index for which to add an alias + * @return true if the alias was created + */ + boolean addAlias(AliasQuery query, IndexCoordinates index); + + /** + * Remove an alias. + * + * @param query query defining the alias + * @param index the index for which to remove an alias + * @return true if the alias was removed + */ + boolean removeAlias(AliasQuery query, IndexCoordinates index); + + /** + * Get the alias informations for a specified index. + * + * @param indexName the name of the index + * @return alias information + */ + List queryForAlias(String indexName); + + /** + * Get settings for a given indexName. + * + * @param indexName the name of the index + * @return the settings + */ + Map getSetting(String indexName); + + /** + * Get settings for a given class. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + * @return the settings + */ + Map getSetting(Class clazz); + + /** + * Refresh the index(es). + * + * @param index the index to refresh + */ + void refresh(IndexCoordinates index); + + /** + * Refresh the index. + * + * @param clazz The entity class, must be annotated with + * {@link org.springframework.data.elasticsearch.annotations.Document} + */ + void refresh(Class clazz); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java new file mode 100644 index 000000000..bba9582ea --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java @@ -0,0 +1,186 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.Query; +import reactor.core.publisher.Mono; + +import org.springframework.util.Assert; + +/** + * The reactive operations for the + * Elasticsearch Document APIs. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +public interface ReactiveDocumentOperations { + /** + * Index the given entity, once available, extracting index and type from entity metadata. + * + * @param entityPublisher must not be {@literal null}. + * @param + * @return a {@link Mono} emitting the saved entity. + */ + default Mono save(Mono entityPublisher) { + + Assert.notNull(entityPublisher, "EntityPublisher must not be null!"); + return entityPublisher.flatMap(this::save); + } + + /** + * Index the given entity extracting index and type from entity metadata. + * + * @param entity must not be {@literal null}. + * @param + * @return a {@link Mono} emitting the saved entity. + */ + Mono save(T entity); + + /** + * Index the entity, once available, under the given {@literal type} in the given {@literal index}. If the + * {@literal index} is {@literal null} or empty the index name provided via entity metadata is used. Same for the + * {@literal type}. + * + * @param entityPublisher must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @param + * @return a {@link Mono} emitting the saved entity. + */ + default Mono save(Mono entityPublisher, IndexCoordinates index) { + + Assert.notNull(entityPublisher, "EntityPublisher must not be null!"); + return entityPublisher.flatMap(it -> save(it, index)); + } + + /** + * Index the entity under the given {@literal type} in the given {@literal index}. If the {@literal index} is + * {@literal null} or empty the index name provided via entity metadata is used. Same for the {@literal type}. + * + * @param entity must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @param + * @return a {@link Mono} emitting the saved entity. + */ + Mono save(T entity, IndexCoordinates index); + + /** + * Find the document with the given {@literal id} mapped onto the given {@literal entityType}. + * + * @param id the {@literal _id} of the document to fetch. + * @param entityType the domain type used for mapping the document. + * @param + * @return {@link Mono#empty()} if not found. + */ + Mono findById(String id, Class entityType); + + /** + * Fetch the entity with given {@literal id}. + * + * @param id must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @param + * @return the {@link Mono} emitting the entity or signalling completion if none found. + */ + Mono findById(String id, Class entityType, IndexCoordinates index); + + /** + * Check if an entity with given {@literal id} exists. + * + * @param id the {@literal _id} of the document to look for. + * @param entityType the domain type used. + * @return a {@link Mono} emitting {@literal true} if a matching document exists, {@literal false} otherwise. + */ + Mono exists(String id, Class entityType); + + /** + * Check if an entity with given {@literal id} exists. + * + * @param id the {@literal _id} of the document to look for. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting {@literal true} if a matching document exists, {@literal false} otherwise. + */ + Mono exists(String id, Class entityType, IndexCoordinates index); + + /** + * Delete the given entity extracting index and type from entity metadata. + * + * @param entity must not be {@literal null}. + * @return a {@link Mono} emitting the {@literal id} of the removed document. + */ + Mono delete(Object entity); + + /** + * Delete the given entity extracting index and type from entity metadata. + * + * @param entity must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting the {@literal id} of the removed document. + */ + Mono delete(Object entity, IndexCoordinates index); + + /** + * Delete the entity with given {@literal id}. + * + * @param id must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting the {@literal id} of the removed document. + */ + default Mono deleteById(String id, IndexCoordinates index) { + + Assert.notNull(index, "Index must not be null!"); + + return deleteById(id, Object.class, index); + } + + /** + * Delete the entity with given {@literal id} extracting index and type from entity metadata. + * + * @param id must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @return a {@link Mono} emitting the {@literal id} of the removed document. + */ + Mono deleteById(String id, Class entityType); + + /** + * Delete the entity with given {@literal id} extracting index and type from entity metadata. + * + * @param id must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting the {@literal id} of the removed document. + */ + Mono deleteById(String id, Class entityType, IndexCoordinates index); + /** + * Delete the documents matching the given {@link Query} extracting index and type from entity metadata. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @return a {@link Mono} emitting the number of the removed documents. + */ + Mono deleteBy(Query query, Class entityType); + + /** + * Delete the documents matching the given {@link Query} extracting index and type from entity metadata. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting the number of the removed documents. + */ + Mono deleteBy(Query query, Class entityType, IndexCoordinates index); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchOperations.java index 947458f49..880a6d133 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchOperations.java @@ -15,19 +15,12 @@ */ package org.springframework.data.elasticsearch.core; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.elasticsearch.index.query.QueryBuilders; import org.reactivestreams.Publisher; -import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.query.Query; -import org.springframework.data.elasticsearch.core.query.StringQuery; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; /** * Interface that specifies a basic set of Elasticsearch operations executed in a reactive way. @@ -41,7 +34,7 @@ import org.springframework.util.Assert; * @author Peter-Josef Meisch * @since 3.2 */ -public interface ReactiveElasticsearchOperations { +public interface ReactiveElasticsearchOperations extends ReactiveDocumentOperations, ReactiveSearchOperations { /** * Execute within a {@link ClientCallback} managing resources and translating errors. @@ -52,261 +45,6 @@ public interface ReactiveElasticsearchOperations { */ Publisher execute(ClientCallback> callback); - /** - * Index the given entity, once available, extracting index and type from entity metadata. - * - * @param entityPublisher must not be {@literal null}. - * @param - * @return a {@link Mono} emitting the saved entity. - */ - default Mono save(Mono entityPublisher) { - - Assert.notNull(entityPublisher, "EntityPublisher must not be null!"); - return entityPublisher.flatMap(this::save); - } - - /** - * Index the given entity extracting index and type from entity metadata. - * - * @param entity must not be {@literal null}. - * @param - * @return a {@link Mono} emitting the saved entity. - */ - default Mono save(T entity) { - return save(entity, getIndexCoordinatesFor(entity.getClass())); - } - - /** - * Index the entity, once available, under the given {@literal type} in the given {@literal index}. If the - * {@literal index} is {@literal null} or empty the index name provided via entity metadata is used. Same for the - * {@literal type}. - * - * @param entityPublisher must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @param - * @return a {@link Mono} emitting the saved entity. - */ - default Mono save(Mono entityPublisher, IndexCoordinates index) { - - Assert.notNull(entityPublisher, "EntityPublisher must not be null!"); - return entityPublisher.flatMap(it -> save(it, index)); - } - - /** - * Index the entity under the given {@literal type} in the given {@literal index}. If the {@literal index} is - * {@literal null} or empty the index name provided via entity metadata is used. Same for the {@literal type}. - * - * @param entity must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @param - * @return a {@link Mono} emitting the saved entity. - */ - Mono save(T entity, IndexCoordinates index); - - /** - * Find the document with the given {@literal id} mapped onto the given {@literal entityType}. - * - * @param id the {@literal _id} of the document to fetch. - * @param entityType the domain type used for mapping the document. - * @param - * @return {@link Mono#empty()} if not found. - */ - default Mono findById(String id, Class entityType) { - return findById(id, entityType, getIndexCoordinatesFor(entityType)); - } - - /** - * Fetch the entity with given {@literal id}. - * - * @param id must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @param - * @return the {@link Mono} emitting the entity or signalling completion if none found. - */ - Mono findById(String id, Class entityType, IndexCoordinates index); - - /** - * Check if an entity with given {@literal id} exists. - * - * @param id the {@literal _id} of the document to look for. - * @param entityType the domain type used. - * @return a {@link Mono} emitting {@literal true} if a matching document exists, {@literal false} otherwise. - */ - default Mono exists(String id, Class entityType) { - return exists(id, entityType, getIndexCoordinatesFor(entityType)); - } - - /** - * Check if an entity with given {@literal id} exists. - * - * @param id the {@literal _id} of the document to look for. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting {@literal true} if a matching document exists, {@literal false} otherwise. - */ - Mono exists(String id, Class entityType, IndexCoordinates index); - - /** - * Search the index for entities matching the given {@link Query query}.
- * {@link Pageable#isUnpaged() Unpaged} queries may overrule elasticsearch server defaults for page size by either - * delegating to the scroll API or using a max {@link org.elasticsearch.search.builder.SearchSourceBuilder#size(int) - * size}. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param - * @return a {@link Flux} emitting matching entities one by one. - */ - default Flux find(Query query, Class entityType) { - return find(query, entityType, entityType); - } - - /** - * Search the index for entities matching the given {@link Query query}.
- * {@link Pageable#isUnpaged() Unpaged} queries may overrule elasticsearch server defaults for page size by either * - * delegating to the scroll API or using a max {@link org.elasticsearch.search.builder.SearchSourceBuilder#size(int) * - * size}. - * - * @param query must not be {@literal null}. - * @param entityType The entity type for mapping the query. Must not be {@literal null}. - * @param returnType The mapping target type. Must not be {@literal null}. Th - * @param - * @return a {@link Flux} emitting matching entities one by one. - */ - default Flux find(Query query, Class entityType, Class returnType) { - return find(query, entityType, returnType, getIndexCoordinatesFor(entityType)); - } - - /** - * Search the index for entities matching the given {@link Query query}. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @param - * @returnm a {@link Flux} emitting matching entities one by one. - */ - default Flux find(Query query, Class entityType, IndexCoordinates index) { - return find(query, entityType, entityType, index); - } - - /** - * Search the index for entities matching the given {@link Query query}. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param resultType the projection result type. - * @param index the target index, must not be {@literal null} - * @param - * @return a {@link Flux} emitting matching entities one by one. - */ - Flux find(Query query, Class entityType, Class resultType, IndexCoordinates index); - - /** - * Count the number of documents matching the given {@link Query}. - * - * @param entityType must not be {@literal null}. - * @return a {@link Mono} emitting the nr of matching documents. - */ - default Mono count(Class entityType) { - return count(new StringQuery(QueryBuilders.matchAllQuery().toString()), entityType); - } - - /** - * Count the number of documents matching the given {@link Query}. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @return a {@link Mono} emitting the nr of matching documents. - */ - default Mono count(Query query, Class entityType) { - return count(query, entityType, getIndexCoordinatesFor(entityType)); - } - - /** - * Count the number of documents matching the given {@link Query}. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting the nr of matching documents. - */ - Mono count(Query query, Class entityType, IndexCoordinates index); - - /** - * Delete the given entity extracting index and type from entity metadata. - * - * @param entity must not be {@literal null}. - * @return a {@link Mono} emitting the {@literal id} of the removed document. - */ - default Mono delete(Object entity) { - return delete(entity, getIndexCoordinatesFor(entity.getClass())); - } - - /** - * Delete the given entity extracting index and type from entity metadata. - * - * @param entity must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting the {@literal id} of the removed document. - */ - Mono delete(Object entity, IndexCoordinates index); - - /** - * Delete the entity with given {@literal id}. - * - * @param id must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting the {@literal id} of the removed document. - */ - default Mono deleteById(String id, IndexCoordinates index) { - - Assert.notNull(index, "Index must not be null!"); - - return deleteById(id, Object.class, index); - } - - /** - * Delete the entity with given {@literal id} extracting index and type from entity metadata. - * - * @param id must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @return a {@link Mono} emitting the {@literal id} of the removed document. - */ - default Mono deleteById(String id, Class entityType) { - return deleteById(id, entityType, getIndexCoordinatesFor(entityType)); - } - - /** - * Delete the entity with given {@literal id} extracting index and type from entity metadata. - * - * @param id must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting the {@literal id} of the removed document. - */ - Mono deleteById(String id, Class entityType, IndexCoordinates index); - - /** - * Delete the documents matching the given {@link Query} extracting index and type from entity metadata. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @return a {@link Mono} emitting the number of the removed documents. - */ - default Mono deleteBy(Query query, Class entityType) { - return deleteBy(query, entityType, getIndexCoordinatesFor(entityType)); - } - - /** - * Delete the documents matching the given {@link Query} extracting index and type from entity metadata. - * - * @param query must not be {@literal null}. - * @param entityType must not be {@literal null}. - * @param index the target index, must not be {@literal null} - * @return a {@link Mono} emitting the number of the removed documents. - */ - Mono deleteBy(Query query, Class entityType, IndexCoordinates index); - /** * Get the {@link ElasticsearchConverter} used. * @@ -322,10 +60,7 @@ public interface ReactiveElasticsearchOperations { * @return the IndexCoordinates defined on the entity. * @since 4.0 */ - default IndexCoordinates getIndexCoordinatesFor(Class clazz) { - ElasticsearchPersistentEntity entity = getPersistentEntityFor(clazz); - return IndexCoordinates.of(entity.getIndexName()).withTypes(entity.getIndexType()); - } + IndexCoordinates getIndexCoordinatesFor(Class clazz); /** * Callback interface to be used with {@link #execute(ClientCallback)} for operating directly on diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java index 92ced2299..8c308d43c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java @@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core; import static org.elasticsearch.index.VersionType.*; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -48,7 +49,6 @@ import org.elasticsearch.search.sort.SortOrder; import org.reactivestreams.Publisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.elasticsearch.NoSuchIndexException; import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient; @@ -93,6 +93,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera private @Nullable RefreshPolicy refreshPolicy = RefreshPolicy.IMMEDIATE; private @Nullable IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosedIgnoreThrottled(); + // region Initialization public ReactiveElasticsearchTemplate(ReactiveElasticsearchClient client) { this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext())); } @@ -109,19 +110,12 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera this.operations = new EntityOperations(this.mappingContext); this.requestFactory = new RequestFactory(converter); } + // endregion + // region DocumentOperations /* * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#exctute(ClientCallback) - */ - @Override - public Publisher execute(ClientCallback> callback) { - return Flux.defer(() -> callback.doWithClient(getClient())).onErrorMap(this::translateException); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#index(Object, IndexCoordinates) + * @see org.springframework.data.elasticsearch.core.ReactiveDElasticsearchOperations#index(Object, IndexCoordinates) */ @Override public Mono save(T entity, IndexCoordinates index) { @@ -136,6 +130,51 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera }); } + @Override + public Mono save(T entity) { + return save(entity, getIndexCoordinatesFor(entity.getClass())); + } + + /** + * Customization hook on the actual execution result {@link Publisher}.
+ * You know what you're doing here? Well fair enough, go ahead on your own risk. + * + * @param request the already prepared {@link IndexRequest} ready to be executed. + * @return a {@link Mono} emitting the result of the operation. + */ + protected Mono doIndex(IndexRequest request) { + return Mono.from(execute(client -> client.index(request))); + } + + /** + * Customization hook on the actual execution result {@link Publisher}.
+ * + * @param request the already prepared {@link GetRequest} ready to be executed. + * @return a {@link Mono} emitting the result of the operation. + */ + protected Mono doFindById(GetRequest request) { + + return Mono.from(execute(client -> client.get(request))) // + .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); + } + + @Override + public Mono exists(String id, Class entityType) { + return exists(id, entityType, getIndexCoordinatesFor(entityType)); + } + + /** + * Customization hook on the actual execution result {@link Publisher}.
+ * + * @param request the already prepared {@link GetRequest} ready to be executed. + * @return a {@link Mono} emitting the result of the operation. + */ + protected Mono doExists(GetRequest request) { + + return Mono.from(execute(client -> client.exists(request))) // + .onErrorReturn(NoSuchIndexException.class, false); + } + private Mono doIndex(Object value, AdaptibleEntity entity, IndexCoordinates index) { return Mono.defer(() -> { @@ -162,6 +201,11 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera }); } + @Override + public Mono findById(String id, Class entityType) { + return findById(id, entityType, getIndexCoordinatesFor(entityType)); + } + /* * (non-Javadoc) * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#findById(String, Class, IndexCoordinates) @@ -200,6 +244,179 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return Mono.defer(() -> doExists(new GetRequest(index.getIndexName(), index.getTypeName(), id))); } + /* + * (non-Javadoc) + * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#delete(Object, String, String) + */ + @Override + public Mono delete(Object entity, IndexCoordinates index) { + + Entity elasticsearchEntity = operations.forEntity(entity); + + return Mono.defer(() -> doDeleteById(entity, converter.convertId(elasticsearchEntity.getId()), + elasticsearchEntity.getPersistentEntity(), index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#delete(String, Class, IndexCoordinates) + */ + @Override + public Mono deleteById(String id, Class entityType, IndexCoordinates index) { + + Assert.notNull(id, "Id must not be null!"); + + return doDeleteById(null, id, getPersistentEntityFor(entityType), index); + + } + + @Override + public Mono delete(Object entity) { + return delete(entity, getIndexCoordinatesFor(entity.getClass())); + } + + @Override + public Mono deleteById(String id, Class entityType) { + return deleteById(id, entityType, getIndexCoordinatesFor(entityType)); + } + + private Mono doDeleteById(@Nullable Object source, String id, ElasticsearchPersistentEntity entity, + IndexCoordinates index) { + + return Mono.defer(() -> { + + return doDelete(prepareDeleteRequest(source, new DeleteRequest(index.getIndexName(), index.getTypeName(), id))); + }); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#deleteBy(Query, Class, IndexCoordinates) + */ + @Override + public Mono deleteBy(Query query, Class entityType, IndexCoordinates index) { + + Assert.notNull(query, "Query must not be null!"); + + return doDeleteBy(query, getPersistentEntityFor(entityType), index).map(BulkByScrollResponse::getDeleted) + .publishNext(); + } + + @Override + public Mono deleteBy(Query query, Class entityType) { + return deleteBy(query, entityType, getIndexCoordinatesFor(entityType)); + } + + private Flux doDeleteBy(Query query, ElasticsearchPersistentEntity entity, + IndexCoordinates index) { + + return Flux.defer(() -> { + DeleteByQueryRequest request = new DeleteByQueryRequest(index.getIndexNames()); + request.types(index.getTypeNames()); + request.setQuery(mappedQuery(query, entity)); + + return doDeleteBy(prepareDeleteByRequest(request)); + }); + } + + /** + * Customization hook on the actual execution result {@link Publisher}.
+ * + * @param request the already prepared {@link DeleteRequest} ready to be executed. + * @return a {@link Mono} emitting the result of the operation. + */ + protected Mono doDelete(DeleteRequest request) { + + return Mono.from(execute(client -> client.delete(request))) // + + .flatMap(it -> { + + if (HttpStatus.valueOf(it.status().getStatus()).equals(HttpStatus.NOT_FOUND)) { + return Mono.empty(); + } + + return Mono.just(it.getId()); + }) // + .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); + } + + /** + * Customization hook on the actual execution result {@link Publisher}.
+ * + * @param request the already prepared {@link DeleteByQueryRequest} ready to be executed. + * @return a {@link Mono} emitting the result of the operation. + */ + protected Mono doDeleteBy(DeleteByQueryRequest request) { + + return Mono.from(execute(client -> client.deleteBy(request))) // + .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); + } + + /** + * Customization hook to modify a generated {@link DeleteRequest} prior to its execution. Eg. by setting the + * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. + * + * @param source the source object the {@link DeleteRequest} was derived from. My be {@literal null} if using the + * {@literal id} directly. + * @param request the generated {@link DeleteRequest}. + * @return never {@literal null}. + */ + protected DeleteRequest prepareDeleteRequest(@Nullable Object source, DeleteRequest request) { + return prepareWriteRequest(request); + } + + /** + * Customization hook to modify a generated {@link DeleteByQueryRequest} prior to its execution. Eg. by setting the + * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. + * + * @param request the generated {@link DeleteByQueryRequest}. + * @return never {@literal null}. + */ + protected DeleteByQueryRequest prepareDeleteByRequest(DeleteByQueryRequest request) { + + if (refreshPolicy != null && !RefreshPolicy.NONE.equals(refreshPolicy)) { + request = request.setRefresh(true); + } + + if (indicesOptions != null) { + request = request.setIndicesOptions(indicesOptions); + } + + return request; + } + + /** + * Customization hook to modify a generated {@link IndexRequest} prior to its execution. Eg. by setting the + * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. + * + * @param source the source object the {@link IndexRequest} was derived from. + * @param request the generated {@link IndexRequest}. + * @return never {@literal null}. + */ + protected IndexRequest prepareIndexRequest(Object source, IndexRequest request) { + return prepareWriteRequest(request); + } + + /** + * Pre process the write request before it is sent to the server, eg. by setting the + * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. + * + * @param request must not be {@literal null}. + * @param + * @return the processed {@link WriteRequest}. + */ + protected > R prepareWriteRequest(R request) { + + if (refreshPolicy == null) { + return request; + } + + return request.setRefreshPolicy(refreshPolicy); + } + + // endregion + + // region SearchOperations /* * (non-Javadoc) * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#find(Query, Class, Class, IndexCoordinates) @@ -210,6 +427,11 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return doFind(query, entityType, index).map(it -> converter.mapDocument(DocumentAdapters.from(it), resultType)); } + @Override + public Flux find(Query query, Class entityType, Class returnType) { + return find(query, entityType, returnType, getIndexCoordinatesFor(entityType)); + } + private Flux doFind(Query query, Class clazz, IndexCoordinates index) { return Flux.defer(() -> { @@ -227,6 +449,11 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera }); } + @Override + public Mono count(Query query, Class entityType) { + return count(query, entityType, getIndexCoordinatesFor(entityType)); + } + @Override public Mono count(Query query, Class entityType, IndexCoordinates index) { return doCount(query, getPersistentEntityFor(entityType), index); @@ -279,235 +506,6 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return request; } - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#delete(Object, String, String) - */ - @Override - public Mono delete(Object entity, IndexCoordinates index) { - - Entity elasticsearchEntity = operations.forEntity(entity); - - return Mono.defer(() -> doDeleteById(entity, converter.convertId(elasticsearchEntity.getId()), - elasticsearchEntity.getPersistentEntity(), index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#delete(String, Class, IndexCoordinates) - */ - @Override - public Mono deleteById(String id, Class entityType, IndexCoordinates index) { - - Assert.notNull(id, "Id must not be null!"); - - return doDeleteById(null, id, getPersistentEntityFor(entityType), index); - - } - - private Mono doDeleteById(@Nullable Object source, String id, ElasticsearchPersistentEntity entity, - IndexCoordinates index) { - - return Mono.defer(() -> { - - return doDelete(prepareDeleteRequest(source, new DeleteRequest(index.getIndexName(), index.getTypeName(), id))); - }); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#deleteBy(Query, Class, IndexCoordinates) - */ - @Override - public Mono deleteBy(Query query, Class entityType, IndexCoordinates index) { - - Assert.notNull(query, "Query must not be null!"); - - return doDeleteBy(query, getPersistentEntityFor(entityType), index).map(BulkByScrollResponse::getDeleted) - .publishNext(); - } - - private Flux doDeleteBy(Query query, ElasticsearchPersistentEntity entity, - IndexCoordinates index) { - - return Flux.defer(() -> { - DeleteByQueryRequest request = new DeleteByQueryRequest(index.getIndexNames()); - request.types(index.getTypeNames()); - request.setQuery(mappedQuery(query, entity)); - - return doDeleteBy(prepareDeleteByRequest(request)); - }); - } - - // Property Setters / Getters - - /** - * Set the default {@link RefreshPolicy} to apply when writing to Elasticsearch. - * - * @param refreshPolicy can be {@literal null}. - */ - public void setRefreshPolicy(@Nullable RefreshPolicy refreshPolicy) { - this.refreshPolicy = refreshPolicy; - } - - /** - * Set the default {@link IndicesOptions} for {@link SearchRequest search requests}. - * - * @param indicesOptions can be {@literal null}. - */ - public void setIndicesOptions(@Nullable IndicesOptions indicesOptions) { - this.indicesOptions = indicesOptions; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#getElasticsearchConverter() - */ - @Override - public ElasticsearchConverter getElasticsearchConverter() { - return converter; - } - - // Customization Hooks - - /** - * Obtain the {@link ReactiveElasticsearchClient} to operate upon. - * - * @return never {@literal null}. - */ - protected ReactiveElasticsearchClient getClient() { - return this.client; - } - - /** - * Pre process the write request before it is sent to the server, eg. by setting the - * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. - * - * @param request must not be {@literal null}. - * @param - * @return the processed {@link WriteRequest}. - */ - protected > R prepareWriteRequest(R request) { - - if (refreshPolicy == null) { - return request; - } - - return request.setRefreshPolicy(refreshPolicy); - } - - /** - * Customization hook to modify a generated {@link IndexRequest} prior to its execution. Eg. by setting the - * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. - * - * @param source the source object the {@link IndexRequest} was derived from. - * @param request the generated {@link IndexRequest}. - * @return never {@literal null}. - */ - protected IndexRequest prepareIndexRequest(Object source, IndexRequest request) { - return prepareWriteRequest(request); - } - - /** - * Customization hook to modify a generated {@link SearchRequest} prior to its execution. Eg. by setting the - * {@link SearchRequest#indicesOptions(IndicesOptions) indices options} if applicable. - * - * @param request the generated {@link CountRequest}. - * @return never {@literal null}. - */ - protected CountRequest prepareCountRequest(CountRequest request) { - - if (indicesOptions == null) { - return request; - } - - return request.indicesOptions(indicesOptions); - } - - /** - * Customization hook to modify a generated {@link SearchRequest} prior to its execution. Eg. by setting the - * {@link SearchRequest#indicesOptions(IndicesOptions) indices options} if applicable. - * - * @param request the generated {@link SearchRequest}. - * @return never {@literal null}. - */ - protected SearchRequest prepareSearchRequest(SearchRequest request) { - - if (indicesOptions == null) { - return request; - } - - return request.indicesOptions(indicesOptions); - } - - /** - * Customization hook to modify a generated {@link DeleteRequest} prior to its execution. Eg. by setting the - * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. - * - * @param source the source object the {@link DeleteRequest} was derived from. My be {@literal null} if using the - * {@literal id} directly. - * @param request the generated {@link DeleteRequest}. - * @return never {@literal null}. - */ - protected DeleteRequest prepareDeleteRequest(@Nullable Object source, DeleteRequest request) { - return prepareWriteRequest(request); - } - - /** - * Customization hook to modify a generated {@link DeleteByQueryRequest} prior to its execution. Eg. by setting the - * {@link WriteRequest#setRefreshPolicy(String) refresh policy} if applicable. - * - * @param request the generated {@link DeleteByQueryRequest}. - * @return never {@literal null}. - */ - protected DeleteByQueryRequest prepareDeleteByRequest(DeleteByQueryRequest request) { - - if (refreshPolicy != null && !RefreshPolicy.NONE.equals(refreshPolicy)) { - request = request.setRefresh(true); - } - - if (indicesOptions != null) { - request = request.setIndicesOptions(indicesOptions); - } - - return request; - } - - /** - * Customization hook on the actual execution result {@link Publisher}.
- * You know what you're doing here? Well fair enough, go ahead on your own risk. - * - * @param request the already prepared {@link IndexRequest} ready to be executed. - * @return a {@link Mono} emitting the result of the operation. - */ - protected Mono doIndex(IndexRequest request) { - return Mono.from(execute(client -> client.index(request))); - } - - /** - * Customization hook on the actual execution result {@link Publisher}.
- * - * @param request the already prepared {@link GetRequest} ready to be executed. - * @return a {@link Mono} emitting the result of the operation. - */ - protected Mono doFindById(GetRequest request) { - - return Mono.from(execute(client -> client.get(request))) // - .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); - } - - /** - * Customization hook on the actual execution result {@link Publisher}.
- * - * @param request the already prepared {@link GetRequest} ready to be executed. - * @return a {@link Mono} emitting the result of the operation. - */ - protected Mono doExists(GetRequest request) { - - return Mono.from(execute(client -> client.exists(request))) // - .onErrorReturn(NoSuchIndexException.class, false); - } - /** * Customization hook on the actual execution result {@link Publisher}.
* @@ -556,41 +554,35 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); } - /** - * Customization hook on the actual execution result {@link Publisher}.
- * - * @param request the already prepared {@link DeleteRequest} ready to be executed. - * @return a {@link Mono} emitting the result of the operation. - */ - protected Mono doDelete(DeleteRequest request) { + @Nullable + private QueryBuilder mappedFilterQuery(Query query, ElasticsearchPersistentEntity entity) { - return Mono.from(execute(client -> client.delete(request))) // + if (query instanceof NativeSearchQuery) { + return ((NativeSearchQuery) query).getFilter(); + } - .flatMap(it -> { - - if (HttpStatus.valueOf(it.status().getStatus()).equals(HttpStatus.NOT_FOUND)) { - return Mono.empty(); - } - - return Mono.just(it.getId()); - }) // - .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); + return null; } - /** - * Customization hook on the actual execution result {@link Publisher}.
- * - * @param request the already prepared {@link DeleteByQueryRequest} ready to be executed. - * @return a {@link Mono} emitting the result of the operation. - */ - protected Mono doDeleteBy(DeleteByQueryRequest request) { + private QueryBuilder mappedQuery(Query query, ElasticsearchPersistentEntity entity) { - return Mono.from(execute(client -> client.deleteBy(request))) // - .onErrorResume(NoSuchIndexException.class, it -> Mono.empty()); + // TODO: we need to actually map the fields to the according field names! + + QueryBuilder elasticsearchQuery = null; + + if (query instanceof CriteriaQuery) { + elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(((CriteriaQuery) query).getCriteria()); + } else if (query instanceof StringQuery) { + elasticsearchQuery = new WrapperQueryBuilder(((StringQuery) query).getSource()); + } else if (query instanceof NativeSearchQuery) { + elasticsearchQuery = ((NativeSearchQuery) query).getQuery(); + } else { + throw new IllegalArgumentException(String.format("Unknown query type '%s'.", query.getClass())); + } + + return elasticsearchQuery != null ? elasticsearchQuery : QueryBuilders.matchAllQuery(); } - // private helpers - private static List sort(Query query, ElasticsearchPersistentEntity entity) { if (query.getSort() == null || query.getSort().isUnsorted()) { @@ -618,33 +610,82 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return mappedSort; } - private QueryBuilder mappedQuery(Query query, ElasticsearchPersistentEntity entity) { + /** + * Customization hook to modify a generated {@link SearchRequest} prior to its execution. Eg. by setting the + * {@link SearchRequest#indicesOptions(IndicesOptions) indices options} if applicable. + * + * @param request the generated {@link CountRequest}. + * @return never {@literal null}. + */ + protected CountRequest prepareCountRequest(CountRequest request) { - // TODO: we need to actually map the fields to the according field names! - - QueryBuilder elasticsearchQuery = null; - - if (query instanceof CriteriaQuery) { - elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(((CriteriaQuery) query).getCriteria()); - } else if (query instanceof StringQuery) { - elasticsearchQuery = new WrapperQueryBuilder(((StringQuery) query).getSource()); - } else if (query instanceof NativeSearchQuery) { - elasticsearchQuery = ((NativeSearchQuery) query).getQuery(); - } else { - throw new IllegalArgumentException(String.format("Unknown query type '%s'.", query.getClass())); + if (indicesOptions == null) { + return request; } - return elasticsearchQuery != null ? elasticsearchQuery : QueryBuilders.matchAllQuery(); + return request.indicesOptions(indicesOptions); } - @Nullable - private QueryBuilder mappedFilterQuery(Query query, ElasticsearchPersistentEntity entity) { + /** + * Customization hook to modify a generated {@link SearchRequest} prior to its execution. Eg. by setting the + * {@link SearchRequest#indicesOptions(IndicesOptions) indices options} if applicable. + * + * @param request the generated {@link SearchRequest}. + * @return never {@literal null}. + */ + protected SearchRequest prepareSearchRequest(SearchRequest request) { - if (query instanceof NativeSearchQuery) { - return ((NativeSearchQuery) query).getFilter(); + if (indicesOptions == null) { + return request; } - return null; + return request.indicesOptions(indicesOptions); + } + + // endregion + + // region Helper methods + // Property Setters / Getters + + /** + * Set the default {@link RefreshPolicy} to apply when writing to Elasticsearch. + * + * @param refreshPolicy can be {@literal null}. + */ + public void setRefreshPolicy(@Nullable RefreshPolicy refreshPolicy) { + this.refreshPolicy = refreshPolicy; + } + + /** + * Set the default {@link IndicesOptions} for {@link SearchRequest search requests}. + * + * @param indicesOptions can be {@literal null}. + */ + public void setIndicesOptions(@Nullable IndicesOptions indicesOptions) { + this.indicesOptions = indicesOptions; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#exctute(ClientCallback) + */ + @Override + public Publisher execute(ClientCallback> callback) { + return Flux.defer(() -> callback.doWithClient(getClient())).onErrorMap(this::translateException); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations#getElasticsearchConverter() + */ + @Override + public ElasticsearchConverter getElasticsearchConverter() { + return converter; + } + + @Override + public IndexCoordinates getIndexCoordinatesFor(Class clazz) { + return getPersistentEntityFor(clazz).getIndexCoordinates(); } @Override @@ -661,4 +702,16 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return potentiallyTranslatedException != null ? potentiallyTranslatedException : throwable; } + + /** + * Obtain the {@link ReactiveElasticsearchClient} to operate upon. + * + * @return never {@literal null}. + */ + protected ReactiveElasticsearchClient getClient() { + return this.client; + } + + // endregion + } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveSearchOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveSearchOperations.java new file mode 100644 index 000000000..dabc23097 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveSearchOperations.java @@ -0,0 +1,119 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.elasticsearch.index.query.QueryBuilders; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.query.Query; +import org.springframework.data.elasticsearch.core.query.StringQuery; + +/** + * The reactive operations for the + * Elasticsearch Document + * APIs. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +public interface ReactiveSearchOperations { + /** + * Search the index for entities matching the given {@link Query query}.
+ * {@link Pageable#isUnpaged() Unpaged} queries may overrule elasticsearch server defaults for page size by either + * delegating to the scroll API or using a max {@link org.elasticsearch.search.builder.SearchSourceBuilder#size(int) + * size}. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param + * @return a {@link Flux} emitting matching entities one by one. + */ + default Flux find(Query query, Class entityType) { + return find(query, entityType, entityType); + } + + /** + * Search the index for entities matching the given {@link Query query}.
+ * {@link Pageable#isUnpaged() Unpaged} queries may overrule elasticsearch server defaults for page size by either * + * delegating to the scroll API or using a max {@link org.elasticsearch.search.builder.SearchSourceBuilder#size(int) * + * size}. + * + * @param query must not be {@literal null}. + * @param entityType The entity type for mapping the query. Must not be {@literal null}. + * @param returnType The mapping target type. Must not be {@literal null}. Th + * @param + * @return a {@link Flux} emitting matching entities one by one. + */ + Flux find(Query query, Class entityType, Class returnType); + + /** + * Search the index for entities matching the given {@link Query query}. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @param + * @returnm a {@link Flux} emitting matching entities one by one. + */ + default Flux find(Query query, Class entityType, IndexCoordinates index) { + return find(query, entityType, entityType, index); + } + + /** + * Search the index for entities matching the given {@link Query query}. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param resultType the projection result type. + * @param index the target index, must not be {@literal null} + * @param + * @return a {@link Flux} emitting matching entities one by one. + */ + Flux find(Query query, Class entityType, Class resultType, IndexCoordinates index); + + /** + * Count the number of documents matching the given {@link Query}. + * + * @param entityType must not be {@literal null}. + * @return a {@link Mono} emitting the nr of matching documents. + */ + default Mono count(Class entityType) { + return count(new StringQuery(QueryBuilders.matchAllQuery().toString()), entityType); + } + + /** + * Count the number of documents matching the given {@link Query}. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @return a {@link Mono} emitting the nr of matching documents. + */ + Mono count(Query query, Class entityType); + + /** + * Count the number of documents matching the given {@link Query}. + * + * @param query must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @param index the target index, must not be {@literal null} + * @return a {@link Mono} emitting the nr of matching documents. + */ + Mono count(Query query, Class entityType, IndexCoordinates index); + +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java index 04e036639..de5fb02d2 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java @@ -66,6 +66,7 @@ import org.springframework.data.elasticsearch.ElasticsearchException; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.*; import org.springframework.lang.Nullable; import org.springframework.util.Assert; diff --git a/src/main/java/org/springframework/data/elasticsearch/core/SearchOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/SearchOperations.java new file mode 100644 index 000000000..14a4d18d6 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/SearchOperations.java @@ -0,0 +1,204 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import java.util.List; +import java.util.stream.Collectors; + +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.search.suggest.SuggestBuilder; +import org.springframework.data.domain.Page; +import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery; +import org.springframework.data.elasticsearch.core.query.Query; +import org.springframework.data.util.CloseableIterator; +import org.springframework.lang.Nullable; + +/** + * The operations for the + * Elasticsearch Document + * APIs. + * + * @author Peter-Josef Meisch + * @since 4.0 + */ +public interface SearchOperations { + /** + * Return number of elements found by given query. + * + * @param query the query to execute + * @param index the index to run the query against + * @return count + */ + default long count(Query query, IndexCoordinates index) { + return count(query, null, index); + } + + /** + * return number of elements found by given query + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return count + */ + long count(Query query, @Nullable Class clazz, IndexCoordinates index); + + T query(Query query, ResultsExtractor resultsExtractor, Class clazz, IndexCoordinates index); + + /** + * Execute the query against elasticsearch and return the first returned object. + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return the first matching object + */ + default T queryForObject(Query query, Class clazz, IndexCoordinates index) { + List content = queryForPage(query, clazz, index).getContent(); + return content.isEmpty() ? null : content.get(0); + } + + /** + * Execute the query against elasticsearch and return result as {@link Page}. + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return a page with aggregations + */ + AggregatedPage queryForPage(Query query, Class clazz, IndexCoordinates index); + + /** + * Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page} + * + * @param queries the queries + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return list of pages with the results + */ + List> queryForPage(List queries, Class clazz, IndexCoordinates index); + + /** + * Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page} + * + * @param queries the queries + * @param classes the entity classes used for the queries + * @param index the index to run the query against + * @return list of pages with the results + */ + List> queryForPage(List queries, List> classes, IndexCoordinates index); + + /** + * Executes the given {@link Query} against elasticsearch and return result as {@link CloseableIterator}. + *

+ * + * @param element return type + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of * + * error. + */ + CloseableIterator stream(Query query, Class clazz, IndexCoordinates index); + + /** + * Execute the criteria query against elasticsearch and return result as {@link List} + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @param element return type + * @return list of found objects + */ + List queryForList(Query query, Class clazz, IndexCoordinates index); + + /** + * Execute the multi search query against elasticsearch and return result as {@link List} + * + * @param queries the queries to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @param element return type + * @return list of found objects + */ + default List> queryForList(List queries, Class clazz, IndexCoordinates index) { + return queryForPage(queries, clazz, index).stream().map(Page::getContent).collect(Collectors.toList()); + } + + /** + * Execute the multi search query against elasticsearch and return result as {@link List} + * + * @param queries the queries to execute + * @param classes the entity classes used for property mapping + * @param index the index to run the query against + * @return list of list of found objects + */ + default List> queryForList(List queries, List> classes, IndexCoordinates index) { + return queryForPage(queries, classes, index).stream().map(Page::getContent).collect(Collectors.toList()); + } + + /** + * Execute the query against elasticsearch and return ids + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @return list of found object ids + */ + List queryForIds(Query query, Class clazz, IndexCoordinates index); + + /** + * Returns scrolled page for given query + * + * @param scrollTimeInMillis duration of the scroll time + * @param query The search query. + * @param clazz The class of entity to retrieve. + * @param index the index to run the query against + * @return scrolled page result + */ + ScrolledPage startScroll(long scrollTimeInMillis, Query query, Class clazz, IndexCoordinates index); + + ScrolledPage continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class clazz); + + /** + * Clears the search contexts associated with specified scroll ids. + * + * @param scrollId the scroll id + */ + void clearScroll(String scrollId); + + /** + * more like this query to search for documents that are "like" a specific document. + * + * @param query the query to execute + * @param clazz the entity clazz used for property mapping + * @param index the index to run the query against + * @param element return type + * @return page with the results + */ + Page moreLikeThis(MoreLikeThisQuery query, Class clazz, IndexCoordinates index); + + /** + * Does a suggest query + * + * @param suggestion the query + * @param index the index to run the query against + * @return the suggest response + */ + SearchResponse suggest(SuggestBuilder suggestion, IndexCoordinates index); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java index 7355a9511..b12ef55cb 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java @@ -31,16 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.data.annotation.Transient; -import org.springframework.data.elasticsearch.annotations.CompletionContext; -import org.springframework.data.elasticsearch.annotations.CompletionField; -import org.springframework.data.elasticsearch.annotations.DynamicMapping; -import org.springframework.data.elasticsearch.annotations.DynamicTemplates; -import org.springframework.data.elasticsearch.annotations.Field; -import org.springframework.data.elasticsearch.annotations.FieldType; -import org.springframework.data.elasticsearch.annotations.GeoPointField; -import org.springframework.data.elasticsearch.annotations.InnerField; -import org.springframework.data.elasticsearch.annotations.Mapping; -import org.springframework.data.elasticsearch.annotations.MultiField; +import org.springframework.data.elasticsearch.annotations.*; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.ResourceUtil; import org.springframework.data.elasticsearch.core.completion.Completion; @@ -111,7 +102,7 @@ public class MappingBuilder { ElasticsearchPersistentEntity entity = elasticsearchConverter.getMappingContext() .getRequiredPersistentEntity(clazz); - XContentBuilder builder = jsonBuilder().startObject().startObject(entity.getIndexType()); + XContentBuilder builder = jsonBuilder().startObject().startObject(entity.getIndexCoordinates().getTypeName()); // Dynamic templates addDynamicTemplatesMapping(builder, entity); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java index e1be3d558..759d38745 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java @@ -32,9 +32,7 @@ import org.springframework.lang.Nullable; */ public interface ElasticsearchPersistentEntity extends PersistentEntity { - String getIndexName(); - - String getIndexType(); + IndexCoordinates getIndexCoordinates(); short getShards(); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/IndexCoordinates.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/IndexCoordinates.java similarity index 97% rename from src/main/java/org/springframework/data/elasticsearch/core/IndexCoordinates.java rename to src/main/java/org/springframework/data/elasticsearch/core/mapping/IndexCoordinates.java index 0cf73c76e..eb1757544 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/IndexCoordinates.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/IndexCoordinates.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.elasticsearch.core; +package org.springframework.data.elasticsearch.core.mapping; import java.util.Arrays; diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java index 93b4e4611..d0dd1705d 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java @@ -102,8 +102,7 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit context.setRootObject(applicationContext); } - @Override - public String getIndexName() { + private String getIndexName() { if (indexName != null) { Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION); @@ -113,8 +112,7 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit return getTypeInformation().getType().getSimpleName(); } - @Override - public String getIndexType() { + private String getIndexType() { if (indexType != null) { Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION); @@ -124,6 +122,11 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit return ""; } + @Override + public IndexCoordinates getIndexCoordinates() { + return IndexCoordinates.of(getIndexName()).withTypes(getIndexType()); + } + @Override public String getIndexStoreType() { return indexStoreType; diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java index 3a7dcd53d..c04043df3 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/ElasticsearchRepository.java @@ -19,6 +19,7 @@ import org.elasticsearch.index.query.QueryBuilder; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.repository.NoRepositoryBean; /** @@ -46,7 +47,7 @@ public interface ElasticsearchRepository extends ElasticsearchCrudReposit Page search(QueryBuilder query, Pageable pageable); - Page search(NativeSearchQuery searchQuery); + Page search(Query searchQuery); Page searchSimilar(T entity, String[] fields, Pageable pageable); diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractReactiveElasticsearchRepositoryQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractReactiveElasticsearchRepositoryQuery.java index 397794ff4..f9303515f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractReactiveElasticsearchRepositoryQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/AbstractReactiveElasticsearchRepositoryQuery.java @@ -20,7 +20,7 @@ import reactor.core.publisher.Mono; import org.reactivestreams.Publisher; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java index 5ee079d33..b0453adc4 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchPartQuery.java @@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.repository.query; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; import org.springframework.data.elasticsearch.core.query.CriteriaQuery; import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator; diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java index 49166c0b9..ebbe03010 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ElasticsearchStringQuery.java @@ -20,7 +20,7 @@ import java.util.regex.Pattern; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.convert.DateTimeConverters; import org.springframework.data.elasticsearch.core.query.StringQuery; import org.springframework.data.repository.query.ParametersParameterAccessor; diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryExecution.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryExecution.java index af02d8080..7ef44c08e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryExecution.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/ReactiveElasticsearchQueryExecution.java @@ -16,7 +16,7 @@ package org.springframework.data.elasticsearch.repository.query; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.repository.query.ResultProcessor; diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/SimpleElasticsearchEntityMetadata.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/SimpleElasticsearchEntityMetadata.java index 857bb8b7b..d900f89ac 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/SimpleElasticsearchEntityMetadata.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/SimpleElasticsearchEntityMetadata.java @@ -38,12 +38,12 @@ public class SimpleElasticsearchEntityMetadata implements ElasticsearchEntity @Override public String getIndexName() { - return entity.getIndexName(); + return entity.getIndexCoordinates().getIndexName(); } @Override public String getIndexTypeName() { - return entity.getIndexType(); + return entity.getIndexCoordinates().getTypeName(); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/AbstractElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/AbstractElasticsearchRepository.java index 8edc1f135..b2f3a7184 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/AbstractElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/AbstractElasticsearchRepository.java @@ -35,14 +35,19 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.DocumentOperations; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.SearchOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.query.DeleteQuery; import org.springframework.data.elasticsearch.core.query.GetQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.data.util.Streamable; import org.springframework.util.Assert; @@ -66,21 +71,23 @@ public abstract class AbstractElasticsearchRepository implements Elastics static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchRepository.class); - protected ElasticsearchOperations elasticsearchOperations; + protected ElasticsearchOperations operations; + protected IndexOperations indexOperations; + protected Class entityClass; protected ElasticsearchEntityInformation entityInformation; public AbstractElasticsearchRepository() {} - public AbstractElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) { - Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null!"); - - this.setElasticsearchOperations(elasticsearchOperations); + public AbstractElasticsearchRepository(ElasticsearchOperations operations) { + Assert.notNull(operations, "ElasticsearchOperations must not be null."); + this.operations = operations; + this.indexOperations = operations.getIndexOperations(); } public AbstractElasticsearchRepository(ElasticsearchEntityInformation metadata, - ElasticsearchOperations elasticsearchOperations) { - this(elasticsearchOperations); + ElasticsearchOperations operations) { + this(operations); Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!"); @@ -97,22 +104,25 @@ public abstract class AbstractElasticsearchRepository implements Elastics } private void createIndex() { - elasticsearchOperations.createIndex(getEntityClass()); + indexOperations.createIndex(getEntityClass()); } private void putMapping() { - elasticsearchOperations.putMapping(getEntityClass()); + indexOperations.putMapping(getEntityClass()); } private boolean createIndexAndMapping() { - return elasticsearchOperations.getPersistentEntityFor(getEntityClass()).isCreateIndexAndMapping(); + + final ElasticsearchPersistentEntity entity = operations.getElasticsearchConverter() + .getMappingContext().getRequiredPersistentEntity(getEntityClass()); + return entity.isCreateIndexAndMapping(); } @Override public Optional findById(ID id) { GetQuery query = new GetQuery(); query.setId(stringIdRepresentation(id)); - return Optional.ofNullable(elasticsearchOperations.get(query, getEntityClass(), getIndexCoordinates())); + return Optional.ofNullable(operations.get(query, getEntityClass(), getIndexCoordinates())); } @Override @@ -128,7 +138,7 @@ public abstract class AbstractElasticsearchRepository implements Elastics @Override public Page findAll(Pageable pageable) { NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build(); - return elasticsearchOperations.queryForPage(query, getEntityClass(), getIndexCoordinates()); + return operations.queryForPage(query, getEntityClass(), getIndexCoordinates()); } @Override @@ -140,27 +150,27 @@ public abstract class AbstractElasticsearchRepository implements Elastics } NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, itemCount, sort)).build(); - return elasticsearchOperations.queryForPage(query, getEntityClass(), getIndexCoordinates()); + return operations.queryForPage(query, getEntityClass(), getIndexCoordinates()); } @Override public Iterable findAllById(Iterable ids) { Assert.notNull(ids, "ids can't be null."); NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build(); - return elasticsearchOperations.multiGet(query, getEntityClass(), getIndexCoordinates()); + return operations.multiGet(query, getEntityClass(), getIndexCoordinates()); } @Override public long count() { NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - return elasticsearchOperations.count(query, getEntityClass(), getIndexCoordinates()); + return operations.count(query, getEntityClass(), getIndexCoordinates()); } @Override public S save(S entity) { Assert.notNull(entity, "Cannot save 'null' entity."); - elasticsearchOperations.index(createIndexQuery(entity), getIndexCoordinates()); - elasticsearchOperations.refresh(getIndexCoordinates()); + operations.index(createIndexQuery(entity), getIndexCoordinates()); + indexOperations.refresh(getIndexCoordinates()); return entity; } @@ -177,7 +187,7 @@ public abstract class AbstractElasticsearchRepository implements Elastics @Override public S indexWithoutRefresh(S entity) { Assert.notNull(entity, "Cannot save 'null' entity."); - elasticsearchOperations.index(createIndexQuery(entity), getIndexCoordinates()); + operations.index(createIndexQuery(entity), getIndexCoordinates()); return entity; } @@ -188,8 +198,8 @@ public abstract class AbstractElasticsearchRepository implements Elastics .collect(Collectors.toList()); if (!queries.isEmpty()) { - elasticsearchOperations.bulkIndex(queries, getIndexCoordinates()); - elasticsearchOperations.refresh(getIndexCoordinates()); + operations.bulkIndex(queries, getIndexCoordinates()); + indexOperations.refresh(getIndexCoordinates()); } return entities; @@ -203,24 +213,24 @@ public abstract class AbstractElasticsearchRepository implements Elastics @Override public Iterable search(QueryBuilder query) { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build(); - int count = (int) elasticsearchOperations.count(searchQuery, getEntityClass(), getIndexCoordinates()); + int count = (int) operations.count(searchQuery, getEntityClass(), getIndexCoordinates()); if (count == 0) { return new PageImpl<>(Collections. emptyList()); } searchQuery.setPageable(PageRequest.of(0, count)); - return elasticsearchOperations.queryForPage(searchQuery, getEntityClass(), getIndexCoordinates()); + return operations.queryForPage(searchQuery, getEntityClass(), getIndexCoordinates()); } @Override public Page search(QueryBuilder query, Pageable pageable) { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build(); - return elasticsearchOperations.queryForPage(searchQuery, getEntityClass(), getIndexCoordinates()); + return operations.queryForPage(searchQuery, getEntityClass(), getIndexCoordinates()); } @Override - public Page search(NativeSearchQuery query) { - return elasticsearchOperations.queryForPage(query, getEntityClass(), getIndexCoordinates()); + public Page search(Query query) { + return operations.queryForPage(query, getEntityClass(), getIndexCoordinates()); } @Override @@ -235,22 +245,22 @@ public abstract class AbstractElasticsearchRepository implements Elastics query.addFields(fields); } - return elasticsearchOperations.moreLikeThis(query, getEntityClass(), getIndexCoordinates()); + return operations.moreLikeThis(query, getEntityClass(), getIndexCoordinates()); } @Override public void deleteById(ID id) { Assert.notNull(id, "Cannot delete entity with id 'null'."); IndexCoordinates indexCoordinates = getIndexCoordinates(); - elasticsearchOperations.delete(stringIdRepresentation(id), indexCoordinates); - elasticsearchOperations.refresh(indexCoordinates); + operations.delete(stringIdRepresentation(id), indexCoordinates); + indexOperations.refresh(indexCoordinates); } @Override public void delete(T entity) { Assert.notNull(entity, "Cannot delete 'null' entity."); deleteById(extractIdFromBean(entity)); - elasticsearchOperations.refresh(getIndexCoordinates()); + indexOperations.refresh(getIndexCoordinates()); } @Override @@ -266,13 +276,13 @@ public abstract class AbstractElasticsearchRepository implements Elastics DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(matchAllQuery()); IndexCoordinates indexCoordinates = getIndexCoordinates(); - elasticsearchOperations.delete(deleteQuery, indexCoordinates); - elasticsearchOperations.refresh(indexCoordinates); + operations.delete(deleteQuery, indexCoordinates); + indexOperations.refresh(indexCoordinates); } @Override public void refresh() { - elasticsearchOperations.refresh(getEntityClass()); + indexOperations.refresh(getEntityClass()); } private IndexQuery createIndexQuery(T entity) { @@ -326,11 +336,6 @@ public abstract class AbstractElasticsearchRepository implements Elastics this.entityClass = entityClass; } - public final void setElasticsearchOperations(ElasticsearchOperations elasticsearchOperations) { - Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null."); - this.elasticsearchOperations = elasticsearchOperations; - } - protected ID extractIdFromBean(T entity) { return entityInformation.getId(entity); } @@ -356,6 +361,6 @@ public abstract class AbstractElasticsearchRepository implements Elastics } private IndexCoordinates getIndexCoordinates() { - return elasticsearchOperations.getIndexCoordinatesFor(getEntityClass()); + return operations.getIndexCoordinatesFor(getEntityClass()); } } diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java index 7383708a0..83bd22fdd 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.repository.support; import org.elasticsearch.index.VersionType; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.repository.core.EntityInformation; /** @@ -25,14 +26,13 @@ import org.springframework.data.repository.core.EntityInformation; * @author Mohsin Husen * @author Christoph Strobl * @author Ivan Greene + * @author Peter-Josef Meisch */ public interface ElasticsearchEntityInformation extends EntityInformation { String getIdAttribute(); - String getIndexName(); - - String getType(); + IndexCoordinates getIndexCoordinates(); Long getVersion(T entity); diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java index 5a8da2f3c..69b8983ac 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.repository.support; import org.elasticsearch.index.VersionType; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; import org.springframework.data.repository.core.support.PersistentEntityInformation; @@ -39,21 +40,19 @@ public class MappingElasticsearchEntityInformation extends PersistentEnti implements ElasticsearchEntityInformation { private final ElasticsearchPersistentEntity entityMetadata; - private final String indexName; - private final String type; + private final IndexCoordinates indexCoordinates; private final VersionType versionType; public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity) { - this(entity, entity.getIndexName(), entity.getIndexType(), entity.getVersionType()); + this(entity, entity.getIndexCoordinates(), entity.getVersionType()); } - public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity, String indexName, String type, - VersionType versionType) { + public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity entity, + IndexCoordinates indexCoordinates, VersionType versionType) { super(entity); this.entityMetadata = entity; - this.indexName = indexName; - this.type = type; + this.indexCoordinates = indexCoordinates; this.versionType = versionType; } @@ -62,14 +61,10 @@ public class MappingElasticsearchEntityInformation extends PersistentEnti return entityMetadata.getRequiredIdProperty().getFieldName(); } - @Override - public String getIndexName() { - return indexName != null ? indexName : entityMetadata.getIndexName(); - } @Override - public String getType() { - return type != null ? type : entityMetadata.getIndexType(); + public IndexCoordinates getIndexCoordinates() { + return indexCoordinates; } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ReactiveElasticsearchRepositoryFactory.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ReactiveElasticsearchRepositoryFactory.java index 8281226de..0ecb9024e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ReactiveElasticsearchRepositoryFactory.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ReactiveElasticsearchRepositoryFactory.java @@ -115,9 +115,8 @@ public class ReactiveElasticsearchRepositoryFactory extends ReactiveRepositoryFa @Nullable RepositoryInformation information) { ElasticsearchPersistentEntity entity = mappingContext.getRequiredPersistentEntity(domainClass); - - return new MappingElasticsearchEntityInformation<>((ElasticsearchPersistentEntity) entity, entity.getIndexName(), - entity.getIndexType(), entity.getVersionType()); + return new MappingElasticsearchEntityInformation<>((ElasticsearchPersistentEntity) entity, + entity.getIndexCoordinates(), entity.getVersionType()); } /** diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java index de2e74a47..3d87f54ce 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java @@ -20,7 +20,6 @@ import reactor.core.publisher.Mono; import org.reactivestreams.Publisher; import org.springframework.data.domain.Sort; -import org.springframework.data.elasticsearch.core.IndexCoordinates; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository; @@ -35,7 +34,6 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla private final ElasticsearchEntityInformation entityInformation; private final ReactiveElasticsearchOperations elasticsearchOperations; - private final IndexCoordinates index; public SimpleReactiveElasticsearchRepository(ElasticsearchEntityInformation entityInformation, ReactiveElasticsearchOperations elasticsearchOperations) { @@ -45,20 +43,19 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla this.entityInformation = entityInformation; this.elasticsearchOperations = elasticsearchOperations; - this.index = IndexCoordinates.of(entityInformation.getIndexName()).withTypes(entityInformation.getType()); } @Override public Flux findAll(Sort sort) { - return elasticsearchOperations.find(Query.findAll().addSort(sort), entityInformation.getJavaType(), index); + return elasticsearchOperations.find(Query.findAll().addSort(sort), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()); } @Override public Mono save(S entity) { Assert.notNull(entity, "Entity must not be null!"); - return elasticsearchOperations.save(entity, index); + return elasticsearchOperations.save(entity, entityInformation.getIndexCoordinates()); } @Override @@ -79,7 +76,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla public Mono findById(ID id) { Assert.notNull(id, "Id must not be null!"); - return elasticsearchOperations.findById(convertId(id), entityInformation.getJavaType(), index); + return elasticsearchOperations.findById(convertId(id), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()); } @Override @@ -93,7 +90,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla public Mono existsById(ID id) { Assert.notNull(id, "Id must not be null!"); - return elasticsearchOperations.exists(convertId(id), entityInformation.getJavaType(), index); + return elasticsearchOperations.exists(convertId(id), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()); } @Override @@ -106,7 +103,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla @Override public Flux findAll() { - return elasticsearchOperations.find(Query.findAll(), entityInformation.getJavaType(), index); + return elasticsearchOperations.find(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()); } @Override @@ -127,14 +124,14 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla @Override public Mono count() { - return elasticsearchOperations.count(Query.findAll(), entityInformation.getJavaType(), index); + return elasticsearchOperations.count(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()); } @Override public Mono deleteById(ID id) { Assert.notNull(id, "Id must not be null!"); - return elasticsearchOperations.deleteById(convertId(id), entityInformation.getJavaType(), index) // + return elasticsearchOperations.deleteById(convertId(id), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()) // .then(); } @@ -149,7 +146,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla public Mono delete(T entity) { Assert.notNull(entity, "Entity must not be null!"); - return elasticsearchOperations.delete(entity, index) // + return elasticsearchOperations.delete(entity, entityInformation.getIndexCoordinates()) // .then(); } @@ -170,7 +167,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla @Override public Mono deleteAll() { - return elasticsearchOperations.deleteBy(Query.findAll(), entityInformation.getJavaType(), index) // + return elasticsearchOperations.deleteBy(Query.findAll(), entityInformation.getJavaType(), entityInformation.getIndexCoordinates()) // .then(); } diff --git a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java index 3afdbcc42..07350522c 100644 --- a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java @@ -45,7 +45,7 @@ import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.data.elasticsearch.annotations.InnerField; import org.springframework.data.elasticsearch.annotations.MultiField; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.GetQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java index 407e0efee..83a286cb3 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplateTests.java @@ -61,7 +61,7 @@ public class ElasticsearchRestTemplateTests extends ElasticsearchTemplateTests { indexRequest.source("{}", XContentType.JSON); UpdateQuery updateQuery = new UpdateQueryBuilder().withId(randomNumeric(5)).withIndexRequest(indexRequest).build(); assertThatThrownBy(() -> { - elasticsearchTemplate.update(updateQuery, index); + operations.update(updateQuery, index); }).isInstanceOf(ElasticsearchStatusException.class); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index ee2718ae0..6aba00fab 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -75,6 +75,7 @@ import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.annotations.ScriptedField; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.*; import org.springframework.data.util.CloseableIterator; @@ -111,18 +112,22 @@ public abstract class ElasticsearchTemplateTests { protected final IndexCoordinates index = IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME); - @Autowired protected ElasticsearchOperations elasticsearchTemplate; + @Autowired protected ElasticsearchOperations operations; + + private IndexOperations indexOperations; @BeforeEach public void before() { + indexOperations = operations.getIndexOperations(); + deleteIndices(); - elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.putMapping(SampleEntity.class); + indexOperations.createIndex(SampleEntity.class); + indexOperations.putMapping(SampleEntity.class); - elasticsearchTemplate.createIndex(SampleEntityUUIDKeyed.class); - elasticsearchTemplate.putMapping(SampleEntityUUIDKeyed.class); + indexOperations.createIndex(SampleEntityUUIDKeyed.class); + indexOperations.putMapping(SampleEntityUUIDKeyed.class); } @AfterEach @@ -133,14 +138,14 @@ public abstract class ElasticsearchTemplateTests { private void deleteIndices() { - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.deleteIndex(SampleEntityUUIDKeyed.class); - elasticsearchTemplate.deleteIndex(UseServerConfigurationEntity.class); - elasticsearchTemplate.deleteIndex(SampleMappingEntity.class); - elasticsearchTemplate.deleteIndex(Book.class); - elasticsearchTemplate.deleteIndex(INDEX_1_NAME); - elasticsearchTemplate.deleteIndex(INDEX_2_NAME); - elasticsearchTemplate.deleteIndex(INDEX_3_NAME); + indexOperations.deleteIndex(SampleEntity.class); + indexOperations.deleteIndex(SampleEntityUUIDKeyed.class); + indexOperations.deleteIndex(UseServerConfigurationEntity.class); + indexOperations.deleteIndex(SampleMappingEntity.class); + indexOperations.deleteIndex(Book.class); + indexOperations.deleteIndex(INDEX_1_NAME); + indexOperations.deleteIndex(INDEX_2_NAME); + indexOperations.deleteIndex(INDEX_3_NAME); } @Test // DATAES-106 @@ -152,13 +157,13 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when - long count = elasticsearchTemplate.count(criteriaQuery, SampleEntity.class, index); + long count = operations.count(criteriaQuery, SampleEntity.class, index); // then assertThat(count).isEqualTo(1); @@ -173,13 +178,13 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - long count = elasticsearchTemplate.count(searchQuery, SampleEntity.class, index); + long count = operations.count(searchQuery, SampleEntity.class, index); // then assertThat(count).isEqualTo(1); } @@ -192,12 +197,12 @@ public abstract class ElasticsearchTemplateTests { SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message("some message") .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); + operations.index(indexQuery, index); // when GetQuery getQuery = new GetQuery(); getQuery.setId(documentId); - SampleEntity sampleEntity1 = elasticsearchTemplate.get(getQuery, SampleEntity.class, index); + SampleEntity sampleEntity1 = operations.get(getQuery, SampleEntity.class, index); // then assertThat(sampleEntity1).isNotNull(); @@ -220,12 +225,12 @@ public abstract class ElasticsearchTemplateTests { List indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)).build(); - List sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class, index); + List sampleEntities = operations.multiGet(query, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(2); @@ -249,13 +254,13 @@ public abstract class ElasticsearchTemplateTests { List indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)) .withFields("message", "type").build(); - List sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class, index); + List sampleEntities = operations.multiGet(query, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(2); @@ -271,13 +276,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities).isNotNull(); @@ -294,15 +299,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQueryWithValidPreference = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPreference("_local").build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQueryWithValidPreference, - SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQueryWithValidPreference, SampleEntity.class, + index); // then assertThat(sampleEntities).isNotNull(); @@ -319,15 +324,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQueryWithInvalidPreference = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPreference("_only_nodes:oops").build(); // when assertThatThrownBy(() -> { - elasticsearchTemplate.queryForPage(searchQueryWithInvalidPreference, SampleEntity.class, index); + operations.queryForPage(searchQueryWithInvalidPreference, SampleEntity.class, index); }).isInstanceOf(Exception.class); } @@ -341,13 +346,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery idxQuery = new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build(); - elasticsearchTemplate.index(idxQuery, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); + operations.index(idxQuery, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withIndicesOptions(IndicesOptions.lenientExpandOpen()).build(); - Page entities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, + Page entities = operations.queryForPage(searchQuery, SampleEntity.class, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); // then @@ -374,12 +379,12 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2)); // when - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(2); } @@ -396,8 +401,8 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); IndexRequest indexRequest = new IndexRequest(); indexRequest.source("message", messageAfterUpdate); @@ -407,12 +412,12 @@ public abstract class ElasticsearchTemplateTests { queries.add(updateQuery); // when - elasticsearchTemplate.bulkUpdate(queries, index); + operations.bulkUpdate(queries, index); // then GetQuery getQuery = new GetQuery(); getQuery.setId(documentId); - SampleEntity indexedEntity = elasticsearchTemplate.get(getQuery, SampleEntity.class, index); + SampleEntity indexedEntity = operations.get(getQuery, SampleEntity.class, index); assertThat(indexedEntity.getMessage()).isEqualTo(messageAfterUpdate); } @@ -426,15 +431,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); + operations.index(indexQuery, index); // when - elasticsearchTemplate.delete(documentId, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(documentId, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(0); } @@ -448,15 +453,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); + operations.index(indexQuery, index); // when - elasticsearchTemplate.delete(documentId, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(documentId, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(0); } @@ -470,18 +475,18 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); // when DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(termQuery("id", documentId)); - elasticsearchTemplate.delete(deleteQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(deleteQuery, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(0); } @@ -496,27 +501,27 @@ public abstract class ElasticsearchTemplateTests { IndexQuery idxQuery1 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build(); - elasticsearchTemplate.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); + operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); IndexQuery idxQuery2 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build(); - elasticsearchTemplate.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); // when DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(typeQuery(TYPE_NAME)); - elasticsearchTemplate.delete(deleteQuery, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME)); + operations.delete(deleteQuery, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "foo")).build(); - assertThat(elasticsearchTemplate.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME))).isEqualTo(0); + assertThat(operations.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME))).isEqualTo(0); } @Test // DATAES-547 @@ -530,27 +535,27 @@ public abstract class ElasticsearchTemplateTests { IndexQuery idxQuery1 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build(); - elasticsearchTemplate.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); + operations.index(idxQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); IndexQuery idxQuery2 = new IndexQueryBuilder().withId(randomNumeric(5)).withObject(sampleEntity).build(); - elasticsearchTemplate.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(idxQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); // when DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(termQuery("message", "negative")); - elasticsearchTemplate.delete(deleteQuery, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME)); + operations.delete(deleteQuery, IndexCoordinates.of("test-index-*").withTypes(TYPE_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "positive")).build(); - assertThat(elasticsearchTemplate.count(searchQuery, IndexCoordinates.of("test-index-*"))).isEqualTo(2); + assertThat(operations.count(searchQuery, IndexCoordinates.of("test-index-*"))).isEqualTo(2); } @Test @@ -562,14 +567,14 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withFilter(boolQuery().filter(termQuery("id", documentId))).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(1); @@ -597,14 +602,14 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withSort(new FieldSortBuilder("rate").order(SortOrder.ASC)).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(3); @@ -633,15 +638,15 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withSort(new FieldSortBuilder("rate").order(SortOrder.ASC)) .withSort(new FieldSortBuilder("message").order(SortOrder.ASC)).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(3); @@ -672,14 +677,14 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsFirst()))).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(3); @@ -710,14 +715,14 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsLast()))).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(3); @@ -734,8 +739,8 @@ public abstract class ElasticsearchTemplateTests { SampleEntity.builder().id("2").message("yellow green").build(), // SampleEntity.builder().id("3").message("blue").build()); - elasticsearchTemplate.bulkIndex(getIndexQueries(entities), index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(getIndexQueries(entities), index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() // .withQuery(matchQuery("message", "green")) // @@ -743,7 +748,7 @@ public abstract class ElasticsearchTemplateTests { .build(); // when - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page.getTotalElements()).isEqualTo(2); @@ -761,13 +766,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(stringQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(1); @@ -788,8 +793,8 @@ public abstract class ElasticsearchTemplateTests { indexQuery.setId(documentId); indexQuery.setObject(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); Map params = new HashMap<>(); params.put("factor", 2); @@ -798,7 +803,7 @@ public abstract class ElasticsearchTemplateTests { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withScriptField( new ScriptField("scriptedRate", new Script(ScriptType.INLINE, "expression", "doc['rate'] * factor", params))) .build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(1); @@ -815,13 +820,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); StringQuery stringQuery = new StringQuery(matchAllQuery().toString(), PageRequest.of(0, 10)); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(stringQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isGreaterThanOrEqualTo(1); @@ -841,14 +846,14 @@ public abstract class ElasticsearchTemplateTests { indexQuery.setId(documentId); indexQuery.setObject(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); StringQuery stringQuery = new StringQuery(matchAllQuery().toString(), PageRequest.of(0, 10), Sort.by(Order.asc("message"))); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(stringQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isGreaterThanOrEqualTo(1); @@ -864,13 +869,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); StringQuery stringQuery = new StringQuery(termQuery("id", documentId).toString()); // when - SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(stringQuery, SampleEntity.class, index); + SampleEntity sampleEntity1 = operations.queryForObject(stringQuery, SampleEntity.class, index); // then assertThat(sampleEntity1).isNotNull(); @@ -881,12 +886,10 @@ public abstract class ElasticsearchTemplateTests { public void shouldCreateIndexGivenEntityClass() { // when - boolean created = elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.putMapping(SampleEntity.class); - Map setting = elasticsearchTemplate.getSetting(SampleEntity.class); + // creation is done in setup method + Map setting = indexOperations.getSetting(SampleEntity.class); // then - assertThat(created).isTrue(); assertThat(setting.get("index.number_of_shards")).isEqualTo("1"); assertThat(setting.get("index.number_of_replicas")).isEqualTo("0"); } @@ -901,12 +904,12 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); // when - SampleEntity sampleEntity1 = elasticsearchTemplate.queryForObject(criteriaQuery, SampleEntity.class, index); + SampleEntity sampleEntity1 = operations.queryForObject(criteriaQuery, SampleEntity.class, index); // then assertThat(sampleEntity1).isNotNull(); @@ -922,17 +925,17 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); // when - elasticsearchTemplate.delete(criteriaQuery, SampleEntity.class, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(criteriaQuery, SampleEntity.class, index); + indexOperations.refresh(SampleEntity.class); // then StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); - List sampleEntities = elasticsearchTemplate.queryForList(stringQuery, SampleEntity.class, index); + List sampleEntities = operations.queryForList(stringQuery, SampleEntity.class, index); assertThat(sampleEntities).isEmpty(); } @@ -949,13 +952,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFields("message") .build(); // when - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page).isNotNull(); @@ -977,8 +980,8 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); FetchSourceFilterBuilder sourceFilter = new FetchSourceFilterBuilder(); sourceFilter.withIncludes("message"); @@ -987,7 +990,7 @@ public abstract class ElasticsearchTemplateTests { .withSourceFilter(sourceFilter.build()).build(); // when - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page).isNotNull(); @@ -1011,15 +1014,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); + operations.index(indexQuery, index); String documentId2 = randomNumeric(5); - elasticsearchTemplate.index( + operations.index( getIndexQuery( SampleEntity.builder().id(documentId2).message(sampleMessage).version(System.currentTimeMillis()).build()), index); - elasticsearchTemplate.refresh(SampleEntity.class); + indexOperations.refresh(SampleEntity.class); MoreLikeThisQuery moreLikeThisQuery = new MoreLikeThisQuery(); moreLikeThisQuery.setId(documentId2); @@ -1027,8 +1030,7 @@ public abstract class ElasticsearchTemplateTests { moreLikeThisQuery.setMinDocFreq(1); // when - Page sampleEntities = elasticsearchTemplate.moreLikeThis(moreLikeThisQuery, SampleEntity.class, - index); + Page sampleEntities = operations.moreLikeThis(moreLikeThisQuery, SampleEntity.class, index); // then assertThat(sampleEntities.getTotalElements()).isEqualTo(1); @@ -1042,21 +1044,20 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); criteriaQuery.setPageable(PageRequest.of(0, 10)); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, - index); + ScrolledPage scroll = operations.startScroll(1000, criteriaQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scroll.getScrollId()); + operations.clearScroll(scroll.getScrollId()); assertThat(sampleEntities).hasSize(30); } @@ -1067,21 +1068,21 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10)).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scroll.getScrollId()); + operations.clearScroll(scroll.getScrollId()); assertThat(sampleEntities).hasSize(30); } @@ -1092,24 +1093,23 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); criteriaQuery.addFields("message"); criteriaQuery.setPageable(PageRequest.of(0, 10)); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, - index); + ScrolledPage scroll = operations.startScroll(1000, criteriaQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1120,22 +1120,22 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFields("message") .withQuery(matchAllQuery()).withPageable(PageRequest.of(0, 10)).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1146,23 +1146,22 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); criteriaQuery.setPageable(PageRequest.of(0, 10)); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, - index); + ScrolledPage scroll = operations.startScroll(1000, criteriaQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1173,22 +1172,22 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10)).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1199,23 +1198,22 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); criteriaQuery.setPageable(PageRequest.of(0, 10)); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, - index); + ScrolledPage scroll = operations.startScroll(1000, criteriaQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1226,22 +1224,22 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10)).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); String scrollId = scroll.getScrollId(); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); - scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); + scroll = operations.continueScroll(scrollId, 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scrollId); + operations.clearScroll(scrollId); assertThat(sampleEntities).hasSize(30); } @@ -1252,14 +1250,14 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); criteriaQuery.setPageable(PageRequest.of(0, 10)); - CloseableIterator stream = elasticsearchTemplate.stream(criteriaQuery, SampleEntity.class, index); + CloseableIterator stream = operations.stream(criteriaQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (stream.hasNext()) { sampleEntities.add(stream.next()); @@ -1307,16 +1305,16 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery singleCriteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); CriteriaQuery multipleCriteriaQuery = new CriteriaQuery( new Criteria("message").contains("some").and("message").contains("message")); - List sampleEntitiesForSingleCriteria = elasticsearchTemplate.queryForList(singleCriteriaQuery, - SampleEntity.class, index); - List sampleEntitiesForAndCriteria = elasticsearchTemplate.queryForList(multipleCriteriaQuery, + List sampleEntitiesForSingleCriteria = operations.queryForList(singleCriteriaQuery, SampleEntity.class, index); + List sampleEntitiesForAndCriteria = operations.queryForList(multipleCriteriaQuery, SampleEntity.class, + index); // then assertThat(sampleEntitiesForSingleCriteria).hasSize(2); assertThat(sampleEntitiesForAndCriteria).hasSize(1); @@ -1344,11 +1342,11 @@ public abstract class ElasticsearchTemplateTests { List indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); - List sampleEntities = elasticsearchTemplate.queryForList(stringQuery, SampleEntity.class, index); + List sampleEntities = operations.queryForList(stringQuery, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(3); @@ -1359,13 +1357,13 @@ public abstract class ElasticsearchTemplateTests { // given Class entity = SampleMappingEntity.class; - elasticsearchTemplate.deleteIndex(entity); - elasticsearchTemplate.createIndex(entity); + indexOperations.deleteIndex(entity); + indexOperations.createIndex(entity); // when // then - assertThat(elasticsearchTemplate.putMapping(entity)).isTrue(); + assertThat(indexOperations.putMapping(entity)).isTrue(); } @Test // DATAES-305 @@ -1373,15 +1371,14 @@ public abstract class ElasticsearchTemplateTests { // given Class entity = SampleEntity.class; - elasticsearchTemplate.deleteIndex(INDEX_1_NAME); - elasticsearchTemplate.createIndex(INDEX_1_NAME); + indexOperations.deleteIndex(INDEX_1_NAME); + indexOperations.createIndex(INDEX_1_NAME); // when - elasticsearchTemplate.putMapping(IndexCoordinates.of(INDEX_1_NAME).withTypes(TYPE_NAME), entity); + indexOperations.putMapping(IndexCoordinates.of(INDEX_1_NAME).withTypes(TYPE_NAME), entity); // then - Map mapping = elasticsearchTemplate - .getMapping(IndexCoordinates.of(INDEX_1_NAME).withTypes(TYPE_NAME)); + Map mapping = indexOperations.getMapping(IndexCoordinates.of(INDEX_1_NAME).withTypes(TYPE_NAME)); assertThat(mapping.get("properties")).isNotNull(); } @@ -1392,10 +1389,10 @@ public abstract class ElasticsearchTemplateTests { Class clazz = SampleEntity.class; // when - elasticsearchTemplate.deleteIndex(clazz); + indexOperations.deleteIndex(clazz); // then - assertThat(elasticsearchTemplate.indexExists(clazz)).isFalse(); + assertThat(indexOperations.indexExists(clazz)).isFalse(); } @Test @@ -1411,20 +1408,20 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); IndexRequest indexRequest = new IndexRequest(); indexRequest.source("message", messageAfterUpdate); UpdateQuery updateQuery = new UpdateQueryBuilder().withId(documentId).withIndexRequest(indexRequest).build(); // when - elasticsearchTemplate.update(updateQuery, index); + operations.update(updateQuery, index); // then GetQuery getQuery = new GetQuery(); getQuery.setId(documentId); - SampleEntity indexedEntity = elasticsearchTemplate.get(getQuery, SampleEntity.class, index); + SampleEntity indexedEntity = operations.get(getQuery, SampleEntity.class, index); assertThat(indexedEntity.getMessage()).isEqualTo(messageAfterUpdate); } @@ -1485,12 +1482,12 @@ public abstract class ElasticsearchTemplateTests { .withIndexRequest(indexRequest).build(); // when - elasticsearchTemplate.update(updateQuery, index); + operations.update(updateQuery, index); // then GetQuery getQuery = new GetQuery(); getQuery.setId(documentId); - SampleEntity indexedEntity = elasticsearchTemplate.get(getQuery, SampleEntity.class, index); + SampleEntity indexedEntity = operations.get(getQuery, SampleEntity.class, index); assertThat(indexedEntity.getMessage()).isEqualTo(message); } @@ -1506,8 +1503,8 @@ public abstract class ElasticsearchTemplateTests { IndexQuery idxQuery = new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build(); IndexCoordinates index = IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type"); - elasticsearchTemplate.index(idxQuery, index); - elasticsearchTemplate.refresh(index); + operations.index(idxQuery, index); + indexOperations.refresh(index); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) @@ -1515,13 +1512,13 @@ public abstract class ElasticsearchTemplateTests { List entities = new ArrayList<>(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(scrollTimeInMillis, searchQuery, - SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(scrollTimeInMillis, searchQuery, SampleEntity.class, + index); entities.addAll(scroll.getContent()); while (scroll.hasContent()) { - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), scrollTimeInMillis, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), scrollTimeInMillis, SampleEntity.class); entities.addAll(scroll.getContent()); } @@ -1541,8 +1538,8 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac").build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when List queries = new ArrayList<>(); @@ -1552,7 +1549,7 @@ public abstract class ElasticsearchTemplateTests { queries.add(new NativeSearchQueryBuilder().withQuery(termQuery("message", "ac")).build()); // then - List> sampleEntities = elasticsearchTemplate.queryForPage(queries, SampleEntity.class, index); + List> sampleEntities = operations.queryForPage(queries, SampleEntity.class, index); for (Page sampleEntity : sampleEntities) { assertThat(sampleEntity.getTotalElements()).isEqualTo(1); } @@ -1563,24 +1560,24 @@ public abstract class ElasticsearchTemplateTests { // given Class clazz = Book.class; - elasticsearchTemplate.deleteIndex(clazz); - elasticsearchTemplate.createIndex(clazz); - elasticsearchTemplate.putMapping(clazz); - elasticsearchTemplate.refresh(clazz); + indexOperations.deleteIndex(clazz); + indexOperations.createIndex(clazz); + indexOperations.putMapping(clazz); + indexOperations.refresh(clazz); IndexCoordinates bookIndex = IndexCoordinates.of("test-index-book-core-template").withTypes("book"); - elasticsearchTemplate.index(buildIndex(SampleEntity.builder().id("1").message("ab").build()), index); - elasticsearchTemplate.index(buildIndex(Book.builder().id("2").description("bc").build()), bookIndex); - elasticsearchTemplate.refresh(SampleEntity.class); - elasticsearchTemplate.refresh(clazz); + operations.index(buildIndex(SampleEntity.builder().id("1").message("ab").build()), index); + operations.index(buildIndex(Book.builder().id("2").description("bc").build()), bookIndex); + indexOperations.refresh(SampleEntity.class); + indexOperations.refresh(clazz); // when List queries = new ArrayList<>(); queries.add(new NativeSearchQueryBuilder().withQuery(termQuery("message", "ab")).build()); queries.add(new NativeSearchQueryBuilder().withQuery(termQuery("description", "bc")).build()); - List> pages = elasticsearchTemplate.queryForPage(queries, Lists.newArrayList(SampleEntity.class, clazz), + List> pages = operations.queryForPage(queries, Lists.newArrayList(SampleEntity.class, clazz), IndexCoordinates.of(index.getIndexName(), bookIndex.getIndexName())); // then @@ -1602,18 +1599,18 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); // when DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(termQuery("id", documentId)); - elasticsearchTemplate.delete(deleteQuery, index); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); + operations.delete(deleteQuery, index); + indexOperations.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(0); } @@ -1627,13 +1624,13 @@ public abstract class ElasticsearchTemplateTests { indexQuery.setSource(documentSource); // when - elasticsearchTemplate.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", indexQuery.getId())) .build(); // then - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(page).isNotNull(); assertThat(page.getContent()).hasSize(1); assertThat(page.getContent().get(0).getId()).isEqualTo(indexQuery.getId()); @@ -1647,8 +1644,9 @@ public abstract class ElasticsearchTemplateTests { indexQuery.setId("2333343434"); // when - assertThatThrownBy(() -> elasticsearchTemplate.index(indexQuery, - IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME))).isInstanceOf(ElasticsearchException.class); + assertThatThrownBy( + () -> operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME))) + .isInstanceOf(ElasticsearchException.class); } @Test @@ -1656,12 +1654,12 @@ public abstract class ElasticsearchTemplateTests { // given List entities = createSampleEntitiesWithMessage("Test message", 30); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "message")) .withPageable(PageRequest.of(0, 100)).build(); // then - List ids = elasticsearchTemplate.queryForIds(searchQuery, SampleEntity.class, index); + List ids = operations.queryForIds(searchQuery, SampleEntity.class, index); assertThat(ids).hasSize(30); } @@ -1674,15 +1672,15 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac").build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(boolQuery().must(wildcardQuery("message", "*a*")).should(wildcardQuery("message", "*b*"))) .withMinScore(2.0F).build(); - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page.getTotalElements()).isEqualTo(1); @@ -1699,14 +1697,14 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac xz hi").build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "xz")) .withSort(SortBuilders.fieldSort("message")).withTrackScores(true).build(); - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page).isInstanceOf(AggregatedPage.class); @@ -1727,14 +1725,14 @@ public abstract class ElasticsearchTemplateTests { indexQuery.setObject(sampleEntity); // when - String documentId = elasticsearchTemplate.index(indexQuery, index); + String documentId = operations.index(indexQuery, index); // then assertThat(sampleEntity.getId()).isEqualTo(documentId); GetQuery getQuery = new GetQuery(); getQuery.setId(documentId); - SampleEntity result = elasticsearchTemplate.get(getQuery, SampleEntity.class, index); + SampleEntity result = operations.get(getQuery, SampleEntity.class, index); assertThat(result.getId()).isEqualTo(documentId); } @@ -1762,12 +1760,12 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(indexQuery2); // when - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(2); List content = sampleEntities.getContent(); @@ -1806,12 +1804,12 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(indexQuery2); // when - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(index); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(index); // then NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, Map.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, Map.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(2); List content = sampleEntities.getContent(); @@ -1830,23 +1828,23 @@ public abstract class ElasticsearchTemplateTests { IndexQueryBuilder indexQueryBuilder = new IndexQueryBuilder().withId(documentId).withVersion(entity.getVersion()) .withObject(entity); - elasticsearchTemplate.index(indexQueryBuilder.build(), index); - elasticsearchTemplate.refresh(index); + operations.index(indexQueryBuilder.build(), index); + indexOperations.refresh(index); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - Page entities = elasticsearchTemplate.queryForPage(searchQuery, GTEVersionEntity.class, index); + Page entities = operations.queryForPage(searchQuery, GTEVersionEntity.class, index); // then assertThat(entities).isNotNull(); assertThat(entities.getTotalElements()).isGreaterThanOrEqualTo(1); // reindex with same version - elasticsearchTemplate.index(indexQueryBuilder.build(), index); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); + operations.index(indexQueryBuilder.build(), index); + indexOperations.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); // reindex with version one below assertThatThrownBy(() -> { - elasticsearchTemplate.index(indexQueryBuilder.withVersion(entity.getVersion() - 1).build(), index); + operations.index(indexQueryBuilder.withVersion(entity.getVersion() - 1).build(), index); }).hasMessageContaining("version").hasMessageContaining("conflict"); } @@ -1860,13 +1858,13 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery = new IndexQueryBuilder().withId(documentId).withObject(sampleEntity).build(); - elasticsearchTemplate.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); + operations.index(indexQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(sampleEntities).isNotNull(); @@ -1882,12 +1880,12 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when - long count = elasticsearchTemplate.count(criteriaQuery, SampleEntity.class, index); + long count = operations.count(criteriaQuery, SampleEntity.class, index); // then assertThat(count).isEqualTo(1); @@ -1902,12 +1900,12 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - long count = elasticsearchTemplate.count(searchQuery, SampleEntity.class, index); + long count = operations.count(searchQuery, SampleEntity.class, index); // then assertThat(count).isEqualTo(1); @@ -1922,12 +1920,12 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when - long count = elasticsearchTemplate.count(criteriaQuery, index); + long count = operations.count(criteriaQuery, index); // then assertThat(count).isEqualTo(1); @@ -1942,12 +1940,12 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - long count = elasticsearchTemplate.count(searchQuery, index); + long count = operations.count(searchQuery, index); // then assertThat(count).isEqualTo(1); @@ -1970,15 +1968,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when - long count = elasticsearchTemplate.count(criteriaQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); + long count = operations.count(criteriaQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); // then assertThat(count).isEqualTo(2); @@ -2001,53 +1999,54 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - long count = elasticsearchTemplate.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); + long count = operations.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); // then assertThat(count).isEqualTo(2); } private void cleanUpIndices() { - elasticsearchTemplate.deleteIndex(INDEX_1_NAME); - elasticsearchTemplate.deleteIndex(INDEX_2_NAME); - elasticsearchTemplate.createIndex(INDEX_1_NAME); - elasticsearchTemplate.createIndex(INDEX_2_NAME); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); + indexOperations.deleteIndex(INDEX_1_NAME); + indexOperations.deleteIndex(INDEX_2_NAME); + indexOperations.createIndex(INDEX_1_NAME); + indexOperations.createIndex(INDEX_2_NAME); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); } @Test // DATAES-71 public void shouldCreatedIndexWithSpecifiedIndexName() { // given - elasticsearchTemplate.deleteIndex(INDEX_3_NAME); + indexOperations.deleteIndex(INDEX_3_NAME); // when - elasticsearchTemplate.createIndex(INDEX_3_NAME); + indexOperations.createIndex(INDEX_3_NAME); // then - assertThat(elasticsearchTemplate.indexExists(INDEX_3_NAME)).isTrue(); + assertThat(indexOperations.indexExists(INDEX_3_NAME)).isTrue(); } @Test // DATAES-72 public void shouldDeleteIndexForSpecifiedIndexName() { // given - elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.refresh(SampleEntity.class); + String indexName = "some-random-index"; + indexOperations.createIndex(indexName); + indexOperations.refresh(IndexCoordinates.of(indexName)); // when - elasticsearchTemplate.deleteIndex(INDEX_3_NAME); + indexOperations.deleteIndex(indexName); // then - assertThat(elasticsearchTemplate.indexExists(INDEX_3_NAME)).isFalse(); + assertThat(indexOperations.indexExists(indexName)).isFalse(); } @Test // DATAES-106 @@ -2067,15 +2066,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when - long count = elasticsearchTemplate.count(criteriaQuery, IndexCoordinates.of(INDEX_1_NAME)); + long count = operations.count(criteriaQuery, IndexCoordinates.of(INDEX_1_NAME)); // then assertThat(count).isEqualTo(1); @@ -2098,15 +2097,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - long count = elasticsearchTemplate.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME)); + long count = operations.count(searchQuery, IndexCoordinates.of(INDEX_1_NAME)); // then assertThat(count).isEqualTo(1); @@ -2121,13 +2120,13 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria()); // when assertThatThrownBy(() -> { - elasticsearchTemplate.count(criteriaQuery, (IndexCoordinates) null); + operations.count(criteriaQuery, (IndexCoordinates) null); }).isInstanceOf(IllegalArgumentException.class); } @@ -2140,13 +2139,13 @@ public abstract class ElasticsearchTemplateTests { .version(System.currentTimeMillis()).build(); IndexQuery indexQuery = getIndexQuery(sampleEntity); - elasticsearchTemplate.index(indexQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.index(indexQuery, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when assertThatThrownBy(() -> { - elasticsearchTemplate.count(searchQuery, (IndexCoordinates) null); + operations.count(searchQuery, (IndexCoordinates) null); }).isInstanceOf(IllegalArgumentException.class); } @@ -2161,14 +2160,14 @@ public abstract class ElasticsearchTemplateTests { + " \"tokenizer\": \"uax_url_email\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; - elasticsearchTemplate.deleteIndex(INDEX_3_NAME); + indexOperations.deleteIndex(INDEX_3_NAME); // when - elasticsearchTemplate.createIndex(INDEX_3_NAME, settings); + indexOperations.createIndex(INDEX_3_NAME, settings); // then - Map map = elasticsearchTemplate.getSetting(INDEX_3_NAME); - assertThat(elasticsearchTemplate.indexExists(INDEX_3_NAME)).isTrue(); + Map map = indexOperations.getSetting(INDEX_3_NAME); + assertThat(indexOperations.indexExists(INDEX_3_NAME)).isTrue(); assertThat(map.containsKey("index.analysis.analyzer.emailAnalyzer.tokenizer")).isTrue(); assertThat(map.get("index.analysis.analyzer.emailAnalyzer.tokenizer")).isEqualTo("uax_url_email"); } @@ -2180,8 +2179,8 @@ public abstract class ElasticsearchTemplateTests { // delete , create and apply mapping in before method // then - Map map = elasticsearchTemplate.getSetting(SampleEntity.class); - assertThat(elasticsearchTemplate.indexExists(SampleEntity.class)).isTrue(); + Map map = indexOperations.getSetting(SampleEntity.class); + assertThat(indexOperations.indexExists(SampleEntity.class)).isTrue(); assertThat(map.containsKey("index.refresh_interval")).isTrue(); assertThat(map.containsKey("index.number_of_replicas")).isTrue(); assertThat(map.containsKey("index.number_of_shards")).isTrue(); @@ -2204,14 +2203,14 @@ public abstract class ElasticsearchTemplateTests { + " }\n" + " }\n" + " }\n" + "}"; // when - elasticsearchTemplate.deleteIndex(SampleEntity.class); - elasticsearchTemplate.createIndex(SampleEntity.class, settings); - elasticsearchTemplate.putMapping(SampleEntity.class); - elasticsearchTemplate.refresh(SampleEntity.class); + indexOperations.deleteIndex(SampleEntity.class); + indexOperations.createIndex(SampleEntity.class, settings); + indexOperations.putMapping(SampleEntity.class); + indexOperations.refresh(SampleEntity.class); // then - Map map = elasticsearchTemplate.getSetting(SampleEntity.class); - assertThat(elasticsearchTemplate.indexExists(INDEX_NAME_SAMPLE_ENTITY)).isTrue(); + Map map = indexOperations.getSetting(SampleEntity.class); + assertThat(indexOperations.indexExists(INDEX_NAME_SAMPLE_ENTITY)).isTrue(); assertThat(map.containsKey("index.number_of_replicas")).isTrue(); assertThat(map.containsKey("index.number_of_shards")).isTrue(); assertThat((String) map.get("index.number_of_replicas")).isEqualTo("0"); @@ -2234,15 +2233,15 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery2 = new IndexQueryBuilder().withId(sampleEntity2.getId()).withObject(sampleEntity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("test-type")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("test-type")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); // when - List sampleEntities = elasticsearchTemplate.queryForList(searchQuery, SampleEntity.class, + List sampleEntities = operations.queryForList(searchQuery, SampleEntity.class, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); // then @@ -2262,14 +2261,14 @@ public abstract class ElasticsearchTemplateTests { IndexQuery indexQuery1 = new IndexQueryBuilder().withId(entity1.getId()).withObject(entity1).build(); IndexQuery indexQuery2 = new IndexQueryBuilder().withId(entity2.getId()).withObject(entity2).build(); - elasticsearchTemplate.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("hetro")); - elasticsearchTemplate.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("hetro")); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_1_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_2_NAME)); + operations.index(indexQuery1, IndexCoordinates.of(INDEX_1_NAME).withTypes("hetro")); + operations.index(indexQuery2, IndexCoordinates.of(INDEX_2_NAME).withTypes("hetro")); + indexOperations.refresh(IndexCoordinates.of(INDEX_1_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_2_NAME)); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class, + Page page = operations.queryForPage(searchQuery, ResultAggregator.class, IndexCoordinates.of(INDEX_1_NAME, INDEX_2_NAME)); assertThat(page.getTotalElements()).isEqualTo(2); @@ -2281,11 +2280,11 @@ public abstract class ElasticsearchTemplateTests { // given // when - boolean created = elasticsearchTemplate.createIndex(UseServerConfigurationEntity.class); + boolean created = indexOperations.createIndex(UseServerConfigurationEntity.class); // then assertThat(created).isTrue(); - Map setting = elasticsearchTemplate.getSetting(UseServerConfigurationEntity.class); + Map setting = indexOperations.getSetting(UseServerConfigurationEntity.class); assertThat(setting.get("index.number_of_shards")).isEqualTo("1"); assertThat(setting.get("index.number_of_replicas")).isEqualTo("1"); } @@ -2296,12 +2295,9 @@ public abstract class ElasticsearchTemplateTests { // given // when - boolean created = elasticsearchTemplate.createIndex(SampleEntity.class); - elasticsearchTemplate.putMapping(SampleEntity.class); - Map mapping = elasticsearchTemplate.getMapping(SampleEntity.class); + Map mapping = indexOperations.getMapping(SampleEntity.class); // then - assertThat(created).isTrue(); assertThat(mapping).isNotNull(); assertThat(((Map) ((Map) mapping.get("properties")).get("message")).get("type")) .isEqualTo("text"); @@ -2321,19 +2317,19 @@ public abstract class ElasticsearchTemplateTests { String remainingDocumentId = UUID.randomUUID().toString(); indexQueries.add(getIndexQuery(SampleEntity.builder().id(remainingDocumentId).message("some other message") .version(System.currentTimeMillis()).build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when DeleteQuery deleteQuery = new DeleteQuery(); deleteQuery.setQuery(idsQuery().addIds(documentIdToDelete)); - elasticsearchTemplate.delete(deleteQuery, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(deleteQuery, index); + indexOperations.refresh(SampleEntity.class); // then // document with id "remainingDocumentId" should still be indexed NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(1); assertThat(sampleEntities.getContent().get(0).getId()).isEqualTo(remainingDocumentId); } @@ -2353,18 +2349,18 @@ public abstract class ElasticsearchTemplateTests { String remainingDocumentId = UUID.randomUUID().toString(); indexQueries.add(getIndexQuery(SampleEntity.builder().id(remainingDocumentId).message("some other message") .version(System.currentTimeMillis()).build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("id").is(documentIdToDelete)); - elasticsearchTemplate.delete(criteriaQuery, SampleEntity.class, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(criteriaQuery, SampleEntity.class, index); + indexOperations.refresh(SampleEntity.class); // then // document with id "remainingDocumentId" should still be indexed NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(1); assertThat(sampleEntities.getContent().get(0).getId()).isEqualTo(remainingDocumentId); } @@ -2383,17 +2379,17 @@ public abstract class ElasticsearchTemplateTests { String remainingDocumentId = UUID.randomUUID().toString(); indexQueries.add(getIndexQuery(SampleEntity.builder().id(remainingDocumentId).message("some other message") .version(System.currentTimeMillis()).build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when - elasticsearchTemplate.delete(documentIdToDelete, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.delete(documentIdToDelete, index); + indexOperations.refresh(SampleEntity.class); // then // document with id "remainingDocumentId" should still be indexed NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page sampleEntities = operations.queryForPage(searchQuery, SampleEntity.class, index); assertThat(sampleEntities.getTotalElements()).isEqualTo(1L); assertThat(sampleEntities.getContent().get(0).getId()).isEqualTo(remainingDocumentId); } @@ -2412,21 +2408,20 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(getIndexQuery(SampleEntity.builder().id(UUID.randomUUID().toString()).message(notFindableMessage) .version(System.currentTimeMillis()).build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("message")); criteriaQuery.setPageable(PageRequest.of(0, 10)); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class, - index); + ScrolledPage scroll = operations.startScroll(1000, criteriaQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scroll.getScrollId()); + operations.clearScroll(scroll.getScrollId()); // then assertThat(sampleEntities).hasSize(2); @@ -2448,20 +2443,20 @@ public abstract class ElasticsearchTemplateTests { indexQueries.add(getIndexQuery(SampleEntity.builder().id(UUID.randomUUID().toString()).message(notFindableMessage) .version(System.currentTimeMillis()).build())); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); // when NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("message", "message")) .withPageable(PageRequest.of(0, 10)).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scroll.getScrollId()); + operations.clearScroll(scroll.getScrollId()); // then assertThat(sampleEntities).hasSize(2); @@ -2476,8 +2471,8 @@ public abstract class ElasticsearchTemplateTests { List entities = createSampleEntitiesWithMessage("Test message", 3); // when - elasticsearchTemplate.bulkIndex(entities, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(entities, index); + indexOperations.refresh(SampleEntity.class); // then SourceFilter sourceFilter = new FetchSourceFilter(new String[] { "id" }, new String[] {}); @@ -2485,13 +2480,13 @@ public abstract class ElasticsearchTemplateTests { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable(PageRequest.of(0, 10)).withSourceFilter(sourceFilter).build(); - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } - elasticsearchTemplate.clearScroll(scroll.getScrollId()); + operations.clearScroll(scroll.getScrollId()); assertThat(sampleEntities).hasSize(3); assertThat(sampleEntities.stream().map(SampleEntity::getId).collect(Collectors.toList())) .doesNotContain((String) null); @@ -2521,19 +2516,19 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withSort(new FieldSortBuilder("rate").order(SortOrder.ASC)) .withSort(new FieldSortBuilder("message").order(SortOrder.DESC)).withPageable(PageRequest.of(0, 10)).build(); // when - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } // then @@ -2567,8 +2562,8 @@ public abstract class ElasticsearchTemplateTests { indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) .withPageable( @@ -2576,11 +2571,11 @@ public abstract class ElasticsearchTemplateTests { .build(); // when - ScrolledPage scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class, index); + ScrolledPage scroll = operations.startScroll(1000, searchQuery, SampleEntity.class, index); List sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); - scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); + scroll = operations.continueScroll(scroll.getScrollId(), 1000, SampleEntity.class); } // then @@ -2605,14 +2600,14 @@ public abstract class ElasticsearchTemplateTests { List indexQueries = getIndexQueries(Arrays.asList(sampleEntity, sampleEntity2, sampleEntity3)); - elasticsearchTemplate.bulkIndex(indexQueries, index); - elasticsearchTemplate.refresh(SampleEntity.class); + operations.bulkIndex(indexQueries, index); + indexOperations.refresh(SampleEntity.class); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withCollapseField("rate") .build(); // when - Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, index); + Page page = operations.queryForPage(searchQuery, SampleEntity.class, index); // then assertThat(page).isNotNull(); @@ -2645,10 +2640,10 @@ public abstract class ElasticsearchTemplateTests { .build(); // when - elasticsearchTemplate.addAlias(aliasQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); + indexOperations.addAlias(aliasQuery, IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); // then - List aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); + List aliases = indexOperations.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); assertThat(aliases).isNotNull(); assertThat(aliases.get(0).alias()).isEqualTo(aliasName); } @@ -2672,8 +2667,8 @@ public abstract class ElasticsearchTemplateTests { // when IndexCoordinates index = IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY); - elasticsearchTemplate.addAlias(aliasQuery1, index); - elasticsearchTemplate.addAlias(aliasQuery2, index); + indexOperations.addAlias(aliasQuery1, index); + indexOperations.addAlias(aliasQuery2, index); String documentId = randomNumeric(5); SampleEntity entity = SampleEntity.builder() // @@ -2687,10 +2682,10 @@ public abstract class ElasticsearchTemplateTests { .withObject(entity) // .build(); - elasticsearchTemplate.index(indexQuery, IndexCoordinates.of(alias1).withTypes(TYPE_NAME)); + operations.index(indexQuery, IndexCoordinates.of(alias1).withTypes(TYPE_NAME)); // then - List aliasMetaData = elasticsearchTemplate.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); + List aliasMetaData = indexOperations.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); assertThat(aliasMetaData).isNotEmpty(); AliasMetaData aliasMetaData1 = aliasMetaData.get(0); @@ -2704,8 +2699,8 @@ public abstract class ElasticsearchTemplateTests { assertThat(aliasMetaData2.searchRouting()).isEqualTo("1"); // cleanup - elasticsearchTemplate.removeAlias(aliasQuery1, index); - elasticsearchTemplate.removeAlias(aliasQuery2, index); + indexOperations.removeAlias(aliasQuery1, index); + indexOperations.removeAlias(aliasQuery2, index); } @Test // DATAES-70 @@ -2721,7 +2716,7 @@ public abstract class ElasticsearchTemplateTests { .build(); // when - elasticsearchTemplate.addAlias(aliasQuery, index); + indexOperations.addAlias(aliasQuery, index); String documentId = randomNumeric(5); SampleEntity sampleEntity = SampleEntity.builder() // @@ -2735,17 +2730,17 @@ public abstract class ElasticsearchTemplateTests { .withObject(sampleEntity) // .build(); - elasticsearchTemplate.index(indexQuery, IndexCoordinates.of(alias).withTypes(TYPE_NAME)); - elasticsearchTemplate.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); + operations.index(indexQuery, IndexCoordinates.of(alias).withTypes(TYPE_NAME)); + indexOperations.refresh(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)); NativeSearchQuery query = new NativeSearchQueryBuilder() // .withQuery(matchAllQuery()) // .build(); - long count = elasticsearchTemplate.count(query, IndexCoordinates.of(alias)); + long count = operations.count(query, IndexCoordinates.of(alias)); // then - List aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); + List aliases = indexOperations.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); assertThat(aliases).isNotNull(); AliasMetaData aliasMetaData = aliases.get(0); assertThat(aliasMetaData.alias()).isEqualTo(alias); @@ -2754,7 +2749,7 @@ public abstract class ElasticsearchTemplateTests { assertThat(count).isEqualTo(1); // cleanup - elasticsearchTemplate.removeAlias(aliasQuery, index); + indexOperations.removeAlias(aliasQuery, index); } @Test // DATAES-541 @@ -2769,14 +2764,14 @@ public abstract class ElasticsearchTemplateTests { .build(); // when - elasticsearchTemplate.addAlias(aliasQuery, index); - List aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); + indexOperations.addAlias(aliasQuery, index); + List aliases = indexOperations.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); assertThat(aliases).isNotNull(); assertThat(aliases.get(0).alias()).isEqualTo(aliasName); // then - elasticsearchTemplate.removeAlias(aliasQuery, index); - aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); + indexOperations.removeAlias(aliasQuery, index); + aliases = indexOperations.queryForAlias(INDEX_NAME_SAMPLE_ENTITY); assertThat(aliases).isEmpty(); } @@ -2817,7 +2812,7 @@ public abstract class ElasticsearchTemplateTests { } protected RequestFactory getRequestFactory() { - return ((AbstractElasticsearchTemplate) elasticsearchTemplate).getRequestFactory(); + return ((AbstractElasticsearchTemplate) operations).getRequestFactory(); } @Data diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java index 0fdde2b78..e9e150b21 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTransportTemplateTests.java @@ -34,6 +34,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.UpdateQuery; @@ -59,7 +60,7 @@ public class ElasticsearchTransportTemplateTests extends ElasticsearchTemplateTe indexRequest.source("{}", XContentType.JSON); UpdateQuery updateQuery = new UpdateQueryBuilder().withId(randomNumeric(5)).withIndexRequest(indexRequest).build(); assertThatThrownBy(() -> { - elasticsearchTemplate.update(updateQuery, index); + operations.update(updateQuery, index); }).isInstanceOf(DocumentMissingException.class); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/IndexCoordinatesTest.java b/src/test/java/org/springframework/data/elasticsearch/core/IndexCoordinatesTest.java index 1d7650622..12bc66bce 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/IndexCoordinatesTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/IndexCoordinatesTest.java @@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core; import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Test; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; /** * @author Peter-Josef Meisch diff --git a/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java index 46ddeec4d..f3369d4a2 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/LogEntityTests.java @@ -36,6 +36,7 @@ import org.springframework.context.annotation.Import; 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.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateTests.java index 3b3193ffd..8abfa0d60 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateTests.java @@ -24,6 +24,7 @@ import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java index d4c4b7b43..5bd97580b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java @@ -24,6 +24,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java index dc7150264..f05a43000 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/aggregation/ElasticsearchTemplateAggregationTests.java @@ -42,7 +42,7 @@ import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.InnerField; import org.springframework.data.elasticsearch.annotations.MultiField; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.ResultsExtractor; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java index 03cfd7b25..acb204390 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.search.suggest.SuggestBuilder; import org.elasticsearch.search.suggest.SuggestBuilders; import org.elasticsearch.search.suggest.SuggestionBuilder; import org.elasticsearch.search.suggest.completion.CompletionSuggestion; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -35,7 +36,8 @@ import org.springframework.data.elasticsearch.annotations.CompletionField; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; @@ -60,9 +62,17 @@ public class ElasticsearchTemplateCompletionTests { @Autowired private ElasticsearchOperations operations; - private void loadCompletionObjectEntities() { + IndexOperations indexOperations; - IndexInitializer.init(operations, CompletionEntity.class); + @BeforeEach + private void setup() { + indexOperations = operations.getIndexOperations(); + + IndexInitializer.init(indexOperations, CompletionEntity.class); + IndexInitializer.init(indexOperations, AnnotatedCompletionEntity.class); + } + + private void loadCompletionObjectEntities() { List indexQueries = new ArrayList<>(); indexQueries.add( @@ -80,8 +90,6 @@ public class ElasticsearchTemplateCompletionTests { private void loadAnnotatedCompletionObjectEntities() { - IndexInitializer.init(operations, AnnotatedCompletionEntity.class); - NonDocumentEntity nonDocumentEntity = new NonDocumentEntity(); nonDocumentEntity.setSomeField1("foo"); nonDocumentEntity.setSomeField2("bar"); @@ -103,8 +111,6 @@ public class ElasticsearchTemplateCompletionTests { private void loadAnnotatedCompletionObjectEntitiesWithWeights() { - IndexInitializer.init(operations, AnnotatedCompletionEntity.class); - List indexQueries = new ArrayList<>(); indexQueries.add(new AnnotatedCompletionEntityBuilder("1").name("Mewes Kochheim1") .suggest(new String[] { "Mewes Kochheim1" }, 4).buildIndex()); @@ -120,17 +126,6 @@ public class ElasticsearchTemplateCompletionTests { operations.refresh(AnnotatedCompletionEntity.class); } - @Test - public void shouldPutMappingForGivenEntity() throws Exception { - - // given - Class entity = CompletionEntity.class; - operations.createIndex(entity); - - // when - assertThat(operations.putMapping(entity)).isTrue(); - } - @Test public void shouldFindSuggestionsForGivenCriteriaQueryUsingCompletionEntity() { @@ -164,7 +159,7 @@ public class ElasticsearchTemplateCompletionTests { // when SearchResponse suggestResponse = ((AbstractElasticsearchTemplate) operations).suggest( new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder), - IndexCoordinates.of("test-index-core-completion").withTypes("completion-type")); + IndexCoordinates.of("test-index-annotated-completion").withTypes("annotated-completion-type")); CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest"); List options = completionSuggestion.getEntries().get(0).getOptions(); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java index 75e2a0de2..71864d076 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/completion/ElasticsearchTemplateCompletionWithContextsTests.java @@ -33,6 +33,7 @@ import org.elasticsearch.search.suggest.completion.CompletionSuggestion; import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder; import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext; import org.elasticsearch.search.suggest.completion.context.ContextMapping; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -43,7 +44,8 @@ import org.springframework.data.elasticsearch.annotations.CompletionField; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; @@ -64,9 +66,18 @@ public class ElasticsearchTemplateCompletionWithContextsTests { @Autowired private ElasticsearchOperations operations; + private IndexOperations indexOperations; + + @BeforeEach + void setup() { + indexOperations = operations.getIndexOperations(); + + indexOperations.deleteIndex(ContextCompletionEntity.class); + } + private void loadContextCompletionObjectEntities() { - IndexInitializer.init(operations, ContextCompletionEntity.class); + IndexInitializer.init(indexOperations, ContextCompletionEntity.class); NonDocumentEntity nonDocumentEntity = new NonDocumentEntity(); nonDocumentEntity.setSomeField1("foo"); @@ -99,17 +110,6 @@ public class ElasticsearchTemplateCompletionWithContextsTests { operations.refresh(ContextCompletionEntity.class); } - @Test - public void shouldPutMappingForGivenEntity() throws Exception { - - // given - Class entity = ContextCompletionEntity.class; - operations.createIndex(entity); - - // when - assertThat(operations.putMapping(entity)).isTrue(); - } - @Test // DATAES-536 public void shouldFindSuggestionsForGivenCriteriaQueryUsingContextCompletionEntityOfMongo() { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java index 39394a364..dab4f30cb 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java @@ -38,7 +38,8 @@ import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.GeoPointField; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.Criteria; import org.springframework.data.elasticsearch.core.query.CriteriaQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery; @@ -75,11 +76,15 @@ public class ElasticsearchTemplateGeoTests { @Autowired private ElasticsearchOperations operations; + private IndexOperations indexOperations; + @BeforeEach public void before() { - IndexInitializer.init(operations, AuthorMarkerEntity.class); - IndexInitializer.init(operations, LocationMarkerEntity.class); + indexOperations = operations.getIndexOperations(); + + IndexInitializer.init(indexOperations, AuthorMarkerEntity.class); + IndexInitializer.init(indexOperations, LocationMarkerEntity.class); } private void loadClassBaseEntities() { @@ -125,17 +130,6 @@ public class ElasticsearchTemplateGeoTests { operations.refresh(LocationMarkerEntity.class); } - @Test - public void shouldPutMappingForGivenEntityWithGeoLocation() throws Exception { - - // given - Class entity = AuthorMarkerEntity.class; - operations.createIndex(entity); - - // when - assertThat(operations.putMapping(entity)).isTrue(); - } - @Test public void shouldFindAuthorMarkersInRangeForGivenCriteriaQuery() { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java index e9f6167cd..33de2b84f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java @@ -51,7 +51,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; import org.springframework.data.elasticsearch.annotations.*; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.completion.Completion; import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.springframework.data.elasticsearch.core.query.IndexQuery; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java index d99b31b45..83643152b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryTests.java @@ -42,7 +42,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +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.test.context.ContextConfiguration; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/dynamicindex/DynamicIndexEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/dynamicindex/DynamicIndexEntityTests.java index 44ccd10ad..09e080041 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/dynamicindex/DynamicIndexEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/dynamicindex/DynamicIndexEntityTests.java @@ -27,6 +27,7 @@ import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; @@ -57,15 +58,18 @@ public class DynamicIndexEntityTests { @Autowired private DynamicIndexRepository repository; @Autowired private ElasticsearchOperations operations; + private IndexOperations indexOperations; @Autowired private IndexNameProvider indexNameProvider; @BeforeEach public void init() { + indexOperations = operations.getIndexOperations(); + deleteIndexes(); - operations.createIndex("index1"); - operations.createIndex("index2"); + indexOperations.createIndex("index1"); + indexOperations.createIndex("index2"); } @AfterEach @@ -75,8 +79,8 @@ public class DynamicIndexEntityTests { private void deleteIndexes() { - operations.deleteIndex("index1"); - operations.deleteIndex("index2"); + indexOperations.deleteIndex("index1"); + indexOperations.deleteIndex("index2"); } @Test // DATAES-456 diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityTests.java deleted file mode 100644 index 588439f35..000000000 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/nondocument/NonDocumentEntityTests.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2013-2019 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.repositories.nondocument; - -import static org.assertj.core.api.Assertions.*; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.data.annotation.Id; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; - -/** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Peter-Josef Meisch - */ -public class NonDocumentEntityTests { - - @Test - public void shouldNotInitialiseRepositoryWithNonDocument() { - // when - ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/repository-non-document-entity.xml"); - assertThatThrownBy(() -> { - ctx.getBean(NonDocumentEntityRepository.class); - }).isInstanceOf(BeanCreationException.class); - } - - /** - * @author Rizwan Idrees - * @author Mohsin Husen - */ - static class NonDocumentEntity { - - @Id private String someId; - private String someField1; - private String someField2; - - public String getSomeField1() { - return someField1; - } - - public void setSomeField1(String someField1) { - this.someField1 = someField1; - } - - public String getSomeField2() { - return someField2; - } - - public void setSomeField2(String someField2) { - this.someField2 = someField2; - } - } - - /** - * @author Rizwan Idrees - * @author Mohsin Husen - * @author Oliver Gierke - */ - @Lazy - interface NonDocumentEntityRepository extends ElasticsearchRepository {} - -} diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryTests.java index 45eb27605..5bb26bd00 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryTests.java @@ -32,7 +32,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Mapping; import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java index 56d8b9703..1eef7734f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/spel/SpELEntityTests.java @@ -26,7 +26,7 @@ import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/synonym/SynonymRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/synonym/SynonymRepositoryTests.java index 57c19799c..469341a8b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/synonym/SynonymRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/synonym/SynonymRepositoryTests.java @@ -32,7 +32,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Mapping; import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexCoordinates; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; diff --git a/src/test/java/org/springframework/data/elasticsearch/utils/IndexInitializer.java b/src/test/java/org/springframework/data/elasticsearch/utils/IndexInitializer.java index 6924f092c..58a1b2d69 100644 --- a/src/test/java/org/springframework/data/elasticsearch/utils/IndexInitializer.java +++ b/src/test/java/org/springframework/data/elasticsearch/utils/IndexInitializer.java @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.utils; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.IndexOperations; /** * Utility to initialize indexes. @@ -31,9 +32,24 @@ public class IndexInitializer { * * @param operations * @param clazz + * @deprecated since 4.0, use {@link IndexInitializer#init(IndexOperations, Class)} */ public static void init(ElasticsearchOperations operations, Class clazz) { + operations.getIndexOperations().deleteIndex(clazz); + operations.getIndexOperations().createIndex(clazz); + operations.getIndexOperations().putMapping(clazz); + operations.getIndexOperations().refresh(clazz); + } + + /** + * Initialize a fresh index with mappings for {@link Class}. Drops the index if it exists before creation. + * + * @param operations + * @param clazz + */ + public static void init(IndexOperations operations, Class clazz) { + operations.deleteIndex(clazz); operations.createIndex(clazz); operations.putMapping(clazz); diff --git a/src/test/resources/repository-non-document-entity.xml b/src/test/resources/repository-non-document-entity.xml deleted file mode 100644 index e1645c556..000000000 --- a/src/test/resources/repository-non-document-entity.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - -