mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-07-05 18:22:23 +00:00
DATAES-594 - Polishing.
This commit is contained in:
parent
d22b12874d
commit
6a3042c437
@ -32,10 +32,15 @@ import org.springframework.data.repository.NoRepositoryBean;
|
||||
@NoRepositoryBean
|
||||
public interface ElasticsearchRepository<T, ID> extends ElasticsearchCrudRepository<T, ID> {
|
||||
|
||||
<S extends T> S indexWithoutRefresh(S entity);
|
||||
|
||||
<S extends T> S index(S entity);
|
||||
|
||||
/**
|
||||
* This method is intended to be used when many single inserts must be made that cannot be aggregated to be inserted
|
||||
* with {@link #saveAll(Iterable)}. This might lead to a temporary inconsistent state until {@link #refresh()} is
|
||||
* called.
|
||||
*/
|
||||
<S extends T> S indexWithoutRefresh(S entity);
|
||||
|
||||
Iterable<T> search(QueryBuilder query);
|
||||
|
||||
Page<T> search(QueryBuilder query, Pageable pageable);
|
||||
|
@ -61,6 +61,7 @@ import org.springframework.util.Assert;
|
||||
public abstract class AbstractElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> {
|
||||
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchRepository.class);
|
||||
|
||||
protected ElasticsearchOperations elasticsearchOperations;
|
||||
protected Class<T> entityClass;
|
||||
protected ElasticsearchEntityInformation<T, ID> entityInformation;
|
||||
@ -76,6 +77,7 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
public AbstractElasticsearchRepository(ElasticsearchEntityInformation<T, ID> metadata,
|
||||
ElasticsearchOperations elasticsearchOperations) {
|
||||
|
||||
this(elasticsearchOperations);
|
||||
|
||||
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
|
||||
@ -93,19 +95,23 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
}
|
||||
|
||||
private void createIndex() {
|
||||
|
||||
elasticsearchOperations.createIndex(getEntityClass());
|
||||
}
|
||||
|
||||
private void putMapping() {
|
||||
|
||||
elasticsearchOperations.putMapping(getEntityClass());
|
||||
}
|
||||
|
||||
private boolean createIndexAndMapping() {
|
||||
|
||||
return elasticsearchOperations.getPersistentEntityFor(getEntityClass()).isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> findById(ID id) {
|
||||
|
||||
GetQuery query = new GetQuery();
|
||||
query.setId(stringIdRepresentation(id));
|
||||
return Optional.ofNullable(elasticsearchOperations.queryForObject(query, getEntityClass()));
|
||||
@ -113,134 +119,167 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
|
||||
int itemCount = (int) this.count();
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.<T> emptyList());
|
||||
}
|
||||
|
||||
return this.findAll(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(pageable).build();
|
||||
|
||||
return elasticsearchOperations.queryForPage(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(Sort sort) {
|
||||
|
||||
int itemCount = (int) this.count();
|
||||
if (itemCount == 0) {
|
||||
return new PageImpl<>(Collections.<T> emptyList());
|
||||
}
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withPageable(PageRequest.of(0, itemCount, sort)).build();
|
||||
|
||||
return elasticsearchOperations.queryForPage(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAllById(Iterable<ID> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build();
|
||||
|
||||
return elasticsearchOperations.multiGet(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
|
||||
|
||||
return elasticsearchOperations.count(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> S save(S entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
|
||||
elasticsearchOperations.index(createIndexQuery(entity));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public <S extends T> List<S> save(List<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
Assert.notEmpty(entities, "Cannot insert empty List.");
|
||||
|
||||
List<IndexQuery> queries = new ArrayList<>();
|
||||
for (S s : entities) {
|
||||
queries.add(createIndexQuery(s));
|
||||
}
|
||||
elasticsearchOperations.bulkIndex(queries);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> S index(S entity) {
|
||||
|
||||
return save(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method might lead to a temporary inconsistent state until
|
||||
* {@link org.springframework.data.elasticsearch.repository.ElasticsearchRepository#refresh() refresh} is called.
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> S indexWithoutRefresh(S entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
|
||||
elasticsearchOperations.index(createIndexQuery(entity));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
|
||||
List<IndexQuery> queries = new ArrayList<>();
|
||||
for (S s : entities) {
|
||||
queries.add(createIndexQuery(s));
|
||||
}
|
||||
elasticsearchOperations.bulkIndex(queries);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsById(ID id) {
|
||||
|
||||
return findById(id).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> search(QueryBuilder query) {
|
||||
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build();
|
||||
int count = (int) elasticsearchOperations.count(searchQuery, getEntityClass());
|
||||
if (count == 0) {
|
||||
return new PageImpl<>(Collections.<T> emptyList());
|
||||
}
|
||||
|
||||
searchQuery.setPageable(PageRequest.of(0, count));
|
||||
|
||||
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> search(QueryBuilder query, Pageable pageable) {
|
||||
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
|
||||
|
||||
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> search(SearchQuery query) {
|
||||
|
||||
return elasticsearchOperations.queryForPage(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<T> searchSimilar(T entity, 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);
|
||||
}
|
||||
|
||||
return elasticsearchOperations.moreLikeThis(query, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(ID id) {
|
||||
|
||||
Assert.notNull(id, "Cannot delete entity with id 'null'.");
|
||||
|
||||
elasticsearchOperations.delete(entityInformation.getIndexName(), entityInformation.getType(),
|
||||
stringIdRepresentation(id));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
@ -248,13 +287,16 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
|
||||
Assert.notNull(entity, "Cannot delete 'null' entity.");
|
||||
|
||||
deleteById(extractIdFromBean(entity));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Iterable<? extends T> entities) {
|
||||
|
||||
Assert.notNull(entities, "Cannot delete 'null' list.");
|
||||
for (T entity : entities) {
|
||||
delete(entity);
|
||||
@ -263,6 +305,7 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
|
||||
DeleteQuery deleteQuery = new DeleteQuery();
|
||||
deleteQuery.setQuery(matchAllQuery());
|
||||
elasticsearchOperations.delete(deleteQuery, getEntityClass());
|
||||
@ -271,10 +314,12 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
|
||||
elasticsearchOperations.refresh(getEntityClass());
|
||||
}
|
||||
|
||||
private IndexQuery createIndexQuery(T entity) {
|
||||
|
||||
IndexQuery query = new IndexQuery();
|
||||
query.setObject(entity);
|
||||
query.setId(stringIdRepresentation(extractIdFromBean(entity)));
|
||||
@ -285,11 +330,13 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<T> resolveReturnedClassFromGenericType() {
|
||||
|
||||
ParameterizedType parameterizedType = resolveReturnedClassFromGenericType(getClass());
|
||||
return (Class<T>) parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private ParameterizedType resolveReturnedClassFromGenericType(Class<?> clazz) {
|
||||
|
||||
Object genericSuperclass = clazz.getGenericSuperclass();
|
||||
if (genericSuperclass instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
|
||||
@ -298,11 +345,13 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
return parameterizedType;
|
||||
}
|
||||
}
|
||||
|
||||
return resolveReturnedClassFromGenericType(clazz.getSuperclass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getEntityClass() {
|
||||
|
||||
if (!isEntityClassSet()) {
|
||||
try {
|
||||
this.entityClass = resolveReturnedClassFromGenericType();
|
||||
@ -310,20 +359,25 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
throw new InvalidDataAccessApiUsageException("Unable to resolve EntityClass. Please use according setter!", e);
|
||||
}
|
||||
}
|
||||
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
private boolean isEntityClassSet() {
|
||||
|
||||
return entityClass != null;
|
||||
}
|
||||
|
||||
public final void setEntityClass(Class<T> entityClass) {
|
||||
|
||||
Assert.notNull(entityClass, "EntityClass must not be null.");
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
public final void setElasticsearchOperations(ElasticsearchOperations elasticsearchOperations) {
|
||||
|
||||
Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null.");
|
||||
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
}
|
||||
|
||||
@ -332,11 +386,14 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
|
||||
}
|
||||
|
||||
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
|
||||
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
|
||||
List<String> stringIds = new ArrayList<>();
|
||||
for (ID id : ids) {
|
||||
stringIds.add(stringIdRepresentation(id));
|
||||
}
|
||||
|
||||
return stringIds;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
@ -586,7 +585,9 @@ public class SimpleElasticsearchRepositoryTests {
|
||||
// then
|
||||
Page<SampleEntity> entities = repository.search(termQuery("id", documentId), PageRequest.of(0, 50));
|
||||
assertThat(entities.getTotalElements()).isEqualTo(0L);
|
||||
|
||||
repository.refresh();
|
||||
|
||||
entities = repository.search(termQuery("id", documentId), PageRequest.of(0, 50));
|
||||
assertThat(entities.getTotalElements()).isEqualTo(1L);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user