From 391e240b49a73331e8d6faf75e17b5d437dbae6b Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Fri, 15 May 2020 21:15:31 +0200 Subject: [PATCH] DATAES-829 - Deprecate AbstractElasticsearchRepository and cleanup SimpleElasticsearchRepository. Original PR: #458 --- .../AbstractElasticsearchRepository.java | 353 +----------------- .../SimpleElasticsearchRepository.java | 331 +++++++++++++++- 2 files changed, 333 insertions(+), 351 deletions(-) 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 4dcd4a25..a570b138 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 @@ -15,42 +15,7 @@ */ package org.springframework.data.elasticsearch.repository.support; -import static org.elasticsearch.index.query.QueryBuilders.*; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.elasticsearch.index.query.IdsQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.domain.Page; -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.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.IndexOperations; -import org.springframework.data.elasticsearch.core.SearchHit; -import org.springframework.data.elasticsearch.core.SearchHitSupport; -import org.springframework.data.elasticsearch.core.SearchHits; -import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; -import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -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.lang.Nullable; -import org.springframework.util.Assert; /** * Elasticsearch specific repository implementation. Likely to be used as target within @@ -59,323 +24,15 @@ import org.springframework.util.Assert; * @author Rizwan Idrees * @author Mohsin Husen * @author Ryan Henszey - * @author Kevin Leturc - * @author Mark Paluch - * @author Christoph Strobl - * @author Michael Wirth * @author Sascha Woo - * @author Murali Chevuri * @author Peter-Josef Meisch - * @author Aleksei Arsenev + * @deprecated since 4.1, derive from {@link SimpleElasticsearchRepository} instead */ -public abstract class AbstractElasticsearchRepository implements ElasticsearchRepository { - - static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchRepository.class); - - protected ElasticsearchOperations operations; - protected IndexOperations indexOperations; - - protected Class entityClass; - protected @Nullable ElasticsearchEntityInformation entityInformation; +@Deprecated +public abstract class AbstractElasticsearchRepository extends SimpleElasticsearchRepository { public AbstractElasticsearchRepository(ElasticsearchEntityInformation metadata, - ElasticsearchOperations operations) { - this.operations = operations; - - Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!"); - - this.entityInformation = metadata; - this.entityClass = this.entityInformation.getJavaType(); - this.indexOperations = operations.indexOps(this.entityClass); - try { - if (createIndexAndMapping() && !indexOperations.exists()) { - createIndex(); - putMapping(); - } - } catch (Exception exception) { - LOGGER.warn("Cannot create index: {}", exception.getMessage()); - } - } - - private void createIndex() { - indexOperations.create(); - } - - private void putMapping() { - indexOperations.putMapping(entityClass); - } - - private boolean createIndexAndMapping() { - - final ElasticsearchPersistentEntity entity = operations.getElasticsearchConverter().getMappingContext() - .getRequiredPersistentEntity(getEntityClass()); - return entity.isCreateIndexAndMapping(); - } - - @Override - public Optional findById(ID id) { - return Optional.ofNullable(operations.get(stringIdRepresentation(id), getEntityClass(), getIndexCoordinates())); - } - - @Override - public Iterable findAll() { - int itemCount = (int) this.count(); - - if (itemCount == 0) { - return new PageImpl<>(Collections.emptyList()); - } - return this.findAll(PageRequest.of(0, Math.max(1, itemCount))); - } - - @SuppressWarnings("unchecked") - @Override - public Page findAll(Pageable pageable) { - NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build(); - SearchHits searchHits = operations.search(query, getEntityClass(), getIndexCoordinates()); - AggregatedPage> page = SearchHitSupport.page(searchHits, query.getPageable()); - return (Page) SearchHitSupport.unwrapSearchHits(page); - } - - @SuppressWarnings("unchecked") - @Override - public Iterable findAll(Sort sort) { - int itemCount = (int) this.count(); - - if (itemCount == 0) { - return new PageImpl<>(Collections.emptyList()); - } - NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) - .withPageable(PageRequest.of(0, itemCount, sort)).build(); - List> searchHitList = operations.search(query, getEntityClass(), getIndexCoordinates()) - .getSearchHits(); - return (List) SearchHitSupport.unwrapSearchHits(searchHitList); - } - - @Override - public Iterable findAllById(Iterable ids) { - Assert.notNull(ids, "ids can't be null."); - NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build(); - return operations.multiGet(query, getEntityClass(), getIndexCoordinates()); - } - - @Override - public long count() { - NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - return operations.count(query, getEntityClass(), getIndexCoordinates()); - } - - @Override - public S save(S entity) { - - Assert.notNull(entity, "Cannot save 'null' entity."); - - operations.save(entity, getIndexCoordinates()); - operations.indexOps(entity.getClass()).refresh(); - return entity; - } - - public List save(List entities) { - - Assert.notNull(entities, "Cannot insert 'null' as a List."); - - return Streamable.of(saveAll(entities)).stream().collect(Collectors.toList()); - } - - @Override - @Deprecated - public S indexWithoutRefresh(S entity) { - Assert.notNull(entity, "Cannot save 'null' entity."); - operations.save(entity); - return entity; - } - - @Override - public Iterable saveAll(Iterable entities) { - - Assert.notNull(entities, "Cannot insert 'null' as a List."); - - IndexCoordinates indexCoordinates = getIndexCoordinates(); - operations.save(entities, indexCoordinates); - operations.indexOps(indexCoordinates).refresh(); - - return entities; - } - - @Override - public boolean existsById(ID id) { - return operations.exists(stringIdRepresentation(id), getIndexCoordinates()); - } - - @SuppressWarnings("unchecked") - @Override - public Iterable search(QueryBuilder query) { - NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build(); - int count = (int) operations.count(searchQuery, getEntityClass(), getIndexCoordinates()); - - if (count == 0) { - return new PageImpl<>(Collections.emptyList()); - } - searchQuery.setPageable(PageRequest.of(0, count)); - SearchHits searchHits = operations.search(searchQuery, getEntityClass(), getIndexCoordinates()); - AggregatedPage> page = SearchHitSupport.page(searchHits, searchQuery.getPageable()); - return (Page) SearchHitSupport.unwrapSearchHits(page); - } - - @SuppressWarnings("unchecked") - @Override - public Page search(QueryBuilder query, Pageable pageable) { - NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build(); - SearchHits searchHits = operations.search(searchQuery, getEntityClass(), getIndexCoordinates()); - AggregatedPage> page = SearchHitSupport.page(searchHits, searchQuery.getPageable()); - return (Page) SearchHitSupport.unwrapSearchHits(page); - } - - @SuppressWarnings("unchecked") - @Override - public Page search(Query query) { - SearchHits searchHits = operations.search(query, getEntityClass(), getIndexCoordinates()); - AggregatedPage> page = SearchHitSupport.page(searchHits, query.getPageable()); - return (Page) SearchHitSupport.unwrapSearchHits(page); - } - - @SuppressWarnings("unchecked") - @Override - public Page searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) { - - Assert.notNull(entity, "Cannot search similar records for 'null'."); - Assert.notNull(pageable, "'pageable' cannot be 'null'"); - - MoreLikeThisQuery query = new MoreLikeThisQuery(); - query.setId(stringIdRepresentation(extractIdFromBean(entity))); - query.setPageable(pageable); - - if (fields != null) { - query.addFields(fields); - } - - SearchHits searchHits = operations.search(query, getEntityClass(), getIndexCoordinates()); - AggregatedPage> page = SearchHitSupport.page(searchHits, pageable); - return (Page) SearchHitSupport.unwrapSearchHits(page); - } - - @Override - public void deleteById(ID id) { - - Assert.notNull(id, "Cannot delete entity with id 'null'."); - - IndexCoordinates indexCoordinates = getIndexCoordinates(); - doDelete(id, indexCoordinates); - indexOperations.refresh(); - } - - @Override - public void delete(T entity) { - - Assert.notNull(entity, "Cannot delete 'null' entity."); - - IndexCoordinates indexCoordinates = getIndexCoordinates(); - doDelete(extractIdFromBean(entity), indexCoordinates); - indexOperations.refresh(); - } - - @Override - public void deleteAll(Iterable entities) { - - Assert.notNull(entities, "Cannot delete 'null' list."); - - IndexCoordinates indexCoordinates = getIndexCoordinates(); - IdsQueryBuilder idsQueryBuilder = idsQuery(); - for (T entity : entities) { - ID id = extractIdFromBean(entity); - if (id != null) { - idsQueryBuilder.addIds(stringIdRepresentation(id)); - } - } - - if (idsQueryBuilder.ids().isEmpty()) { - return; - } - - Query query = new NativeSearchQueryBuilder().withQuery(idsQueryBuilder).build(); - - operations.delete(query, getEntityClass(), indexCoordinates); - indexOperations.refresh(); - } - - private void doDelete(@Nullable ID id, IndexCoordinates indexCoordinates) { - if (id != null) { - operations.delete(stringIdRepresentation(id), indexCoordinates); - } - } - - @Override - public void deleteAll() { - IndexCoordinates indexCoordinates = getIndexCoordinates(); - Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); - - operations.delete(query, getEntityClass(), indexCoordinates); - indexOperations.refresh(); - } - - @Override - public void refresh() { - indexOperations.refresh(); - } - - @SuppressWarnings("unchecked") - private Class resolveReturnedClassFromGenericType() { - ParameterizedType parameterizedType = resolveReturnedClassFromGenericType(getClass()); - return (Class) parameterizedType.getActualTypeArguments()[0]; - } - - private ParameterizedType resolveReturnedClassFromGenericType(Class clazz) { - Object genericSuperclass = clazz.getGenericSuperclass(); - - if (genericSuperclass instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; - Type rawtype = parameterizedType.getRawType(); - if (SimpleElasticsearchRepository.class.equals(rawtype)) { - return parameterizedType; - } - } - - return resolveReturnedClassFromGenericType(clazz.getSuperclass()); - } - - protected Class getEntityClass() { - - if (!isEntityClassSet()) { - try { - this.entityClass = resolveReturnedClassFromGenericType(); - } catch (Exception e) { - throw new InvalidDataAccessApiUsageException("Unable to resolve EntityClass. Please use according setter!", e); - } - } - return entityClass; - } - - private boolean isEntityClassSet() { - return entityClass != null; - } - - @Nullable - protected ID extractIdFromBean(T entity) { - return entityInformation.getId(entity); - } - - private List stringIdsRepresentation(Iterable ids) { - Assert.notNull(ids, "ids can't be null."); - List stringIds = new ArrayList<>(); - for (ID id : ids) { - stringIds.add(stringIdRepresentation(id)); - } - - return stringIds; - } - - protected abstract @Nullable String stringIdRepresentation(@Nullable ID id); - - private IndexCoordinates getIndexCoordinates() { - return operations.getIndexCoordinatesFor(getEntityClass()); + ElasticsearchOperations elasticsearchOperations) { + super(metadata, elasticsearchOperations); } } diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java index 006bbded..5f56a30c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java @@ -15,8 +15,39 @@ */ package org.springframework.data.elasticsearch.repository.support; +import static org.elasticsearch.index.query.QueryBuilders.*; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.elasticsearch.index.query.IdsQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +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.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHitSupport; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +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.StreamUtils; +import org.springframework.data.util.Streamable; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Elasticsearch specific repository implementation. Likely to be used as target within @@ -25,18 +56,312 @@ import org.springframework.lang.Nullable; * @author Rizwan Idrees * @author Mohsin Husen * @author Ryan Henszey + * @author Kevin Leturc + * @author Mark Paluch + * @author Christoph Strobl + * @author Michael Wirth * @author Sascha Woo + * @author Murali Chevuri * @author Peter-Josef Meisch + * @author Aleksei Arsenev */ -public class SimpleElasticsearchRepository extends AbstractElasticsearchRepository { +public class SimpleElasticsearchRepository implements ElasticsearchRepository { + + private static final Logger LOGGER = LoggerFactory.getLogger(SimpleElasticsearchRepository.class); + + protected ElasticsearchOperations operations; + protected IndexOperations indexOperations; + + protected Class entityClass; + protected ElasticsearchEntityInformation entityInformation; public SimpleElasticsearchRepository(ElasticsearchEntityInformation metadata, - ElasticsearchOperations elasticsearchOperations) { - super(metadata, elasticsearchOperations); + ElasticsearchOperations operations) { + this.operations = operations; + + Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!"); + + this.entityInformation = metadata; + this.entityClass = this.entityInformation.getJavaType(); + this.indexOperations = operations.indexOps(this.entityClass); + try { + if (createIndexAndMapping() && !indexOperations.exists()) { + createIndex(); + putMapping(); + } + } catch (Exception exception) { + LOGGER.warn("Cannot create index: {}", exception.getMessage()); + } + } + + private void createIndex() { + indexOperations.create(); + } + + private void putMapping() { + indexOperations.putMapping(entityClass); + } + + private boolean createIndexAndMapping() { + + final ElasticsearchPersistentEntity entity = operations.getElasticsearchConverter().getMappingContext() + .getRequiredPersistentEntity(entityClass); + return entity.isCreateIndexAndMapping(); } @Override + public Optional findById(ID id) { + return Optional.ofNullable( + execute(operations -> operations.get(stringIdRepresentation(id), entityClass, getIndexCoordinates()))); + } + + @Override + public Iterable findAll() { + int itemCount = (int) this.count(); + + if (itemCount == 0) { + return new PageImpl<>(Collections.emptyList()); + } + return this.findAll(PageRequest.of(0, Math.max(1, itemCount))); + } + + @SuppressWarnings("unchecked") + @Override + public Page findAll(Pageable pageable) { + NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build(); + SearchHits searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates())); + AggregatedPage> page = SearchHitSupport.page(searchHits, query.getPageable()); + return (Page) SearchHitSupport.unwrapSearchHits(page); + } + + @SuppressWarnings("unchecked") + @Override + public Iterable findAll(Sort sort) { + int itemCount = (int) this.count(); + + if (itemCount == 0) { + return new PageImpl<>(Collections.emptyList()); + } + NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withPageable(PageRequest.of(0, itemCount, sort)).build(); + List> searchHitList = execute( + operations -> operations.search(query, entityClass, getIndexCoordinates()).getSearchHits()); + return (List) SearchHitSupport.unwrapSearchHits(searchHitList); + } + + @Override + public Iterable findAllById(Iterable ids) { + Assert.notNull(ids, "ids can't be null."); + NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build(); + // noinspection ConstantConditions + return execute(operations -> operations.multiGet(query, entityClass, getIndexCoordinates())); + } + + @Override + public long count() { + NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + // noinspection ConstantConditions + return execute(operations -> operations.count(query, entityClass, getIndexCoordinates())); + } + + @Override + public S save(S entity) { + + Assert.notNull(entity, "Cannot save 'null' entity."); + + // noinspection ConstantConditions + return executeAndRefresh(operations -> operations.save(entity, getIndexCoordinates())); + } + + public List save(List entities) { + + Assert.notNull(entities, "Cannot insert 'null' as a List."); + + return Streamable.of(saveAll(entities)).stream().collect(Collectors.toList()); + } + + @Override + @Deprecated + public S indexWithoutRefresh(S entity) { + Assert.notNull(entity, "Cannot save 'null' entity."); + // noinspection ConstantConditions + return execute(operations -> operations.save(entity)); + } + + @Override + public Iterable saveAll(Iterable entities) { + + Assert.notNull(entities, "Cannot insert 'null' as a List."); + + IndexCoordinates indexCoordinates = getIndexCoordinates(); + executeAndRefresh(operations -> operations.save(entities, indexCoordinates)); + + return entities; + } + + @Override + public boolean existsById(ID id) { + // noinspection ConstantConditions + return execute(operations -> operations.exists(stringIdRepresentation(id), getIndexCoordinates())); + } + + @SuppressWarnings("unchecked") + @Override + public Iterable search(QueryBuilder query) { + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build(); + long count = execute(operations -> operations.count(searchQuery, entityClass, getIndexCoordinates())); + + if (count == 0) { + return new PageImpl<>(Collections.emptyList()); + } + searchQuery.setPageable(PageRequest.of(0, (int)count)); + SearchHits searchHits = execute( + operations -> operations.search(searchQuery, entityClass, getIndexCoordinates())); + AggregatedPage> page = SearchHitSupport.page(searchHits, searchQuery.getPageable()); + return (Page) SearchHitSupport.unwrapSearchHits(page); + } + + @SuppressWarnings("unchecked") + @Override + public Page search(QueryBuilder query, Pageable pageable) { + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build(); + SearchHits searchHits = execute( + operations -> operations.search(searchQuery, entityClass, getIndexCoordinates())); + AggregatedPage> page = SearchHitSupport.page(searchHits, searchQuery.getPageable()); + return (Page) SearchHitSupport.unwrapSearchHits(page); + } + + @SuppressWarnings("unchecked") + @Override + public Page search(Query query) { + SearchHits searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates())); + AggregatedPage> page = SearchHitSupport.page(searchHits, query.getPageable()); + return (Page) SearchHitSupport.unwrapSearchHits(page); + } + + @SuppressWarnings("unchecked") + @Override + public Page searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) { + + Assert.notNull(entity, "Cannot search similar records for 'null'."); + Assert.notNull(pageable, "'pageable' cannot be 'null'"); + + MoreLikeThisQuery query = new MoreLikeThisQuery(); + query.setId(stringIdRepresentation(extractIdFromBean(entity))); + query.setPageable(pageable); + + if (fields != null) { + query.addFields(fields); + } + + SearchHits searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates())); + AggregatedPage> page = SearchHitSupport.page(searchHits, pageable); + return (Page) SearchHitSupport.unwrapSearchHits(page); + } + + @Override + public void deleteById(ID id) { + + Assert.notNull(id, "Cannot delete entity with id 'null'."); + + doDelete(id, getIndexCoordinates()); + } + + @Override + public void delete(T entity) { + + Assert.notNull(entity, "Cannot delete 'null' entity."); + + doDelete(extractIdFromBean(entity), getIndexCoordinates()); + } + + @Override + public void deleteAll(Iterable entities) { + + Assert.notNull(entities, "Cannot delete 'null' list."); + + IndexCoordinates indexCoordinates = getIndexCoordinates(); + IdsQueryBuilder idsQueryBuilder = idsQuery(); + for (T entity : entities) { + ID id = extractIdFromBean(entity); + if (id != null) { + idsQueryBuilder.addIds(stringIdRepresentation(id)); + } + } + + if (idsQueryBuilder.ids().isEmpty()) { + return; + } + + Query query = new NativeSearchQueryBuilder().withQuery(idsQueryBuilder).build(); + + executeAndRefresh((OperationsCallback) operations -> { + operations.delete(query, entityClass, indexCoordinates); + return null; + }); + } + + private void doDelete(@Nullable ID id, IndexCoordinates indexCoordinates) { + + if (id != null) { + executeAndRefresh(operations -> operations.delete(stringIdRepresentation(id), indexCoordinates)); + } + } + + @Override + public void deleteAll() { + IndexCoordinates indexCoordinates = getIndexCoordinates(); + Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + + executeAndRefresh((OperationsCallback) operations -> { + operations.delete(query, entityClass, indexCoordinates); + return null; + }); + } + + @Override + public void refresh() { + indexOperations.refresh(); + } + + @Nullable + protected ID extractIdFromBean(T entity) { + return entityInformation.getId(entity); + } + + private List stringIdsRepresentation(Iterable ids) { + + Assert.notNull(ids, "ids can't be null."); + + return StreamUtils.createStreamFromIterator(ids.iterator()).map(id -> stringIdRepresentation(id)) + .collect(Collectors.toList()); + } + protected @Nullable String stringIdRepresentation(@Nullable ID id) { return operations.stringIdRepresentation(id); } + + private IndexCoordinates getIndexCoordinates() { + return operations.getIndexCoordinatesFor(entityClass); + } + + // region operations callback + @FunctionalInterface + public interface OperationsCallback { + @Nullable + R doWithOperations(ElasticsearchOperations operations); + } + + @Nullable + public R execute(OperationsCallback callback) { + return callback.doWithOperations(operations); + } + + @Nullable + public R executeAndRefresh(OperationsCallback callback) { + R result = callback.doWithOperations(operations); + refresh(); + return result; + } + // endregion }