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 83a6d4ac6..15e9731e5 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java @@ -340,6 +340,14 @@ public interface ElasticsearchOperations { */ String delete(String indexName, String type, String id); + + /** + * Delete all records matching the criteria + * + * @param clazz + * @param criteriaQuery + */ + void delete(CriteriaQuery criteriaQuery, Class clazz); /** * Delete the one object with provided id * 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 6d2834dcd..22c93f1c4 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -585,6 +585,15 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati .setQuery(deleteQuery.getQuery()).execute().actionGet(); } + @Override + public void delete(CriteriaQuery criteriaQuery, Class clazz) { + QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria()); + Assert.notNull(elasticsearchQuery, "Query can not be null."); + DeleteQuery deleteQuery = new DeleteQuery(); + deleteQuery.setQuery(elasticsearchQuery); + delete(deleteQuery, clazz); + } + @Override public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) { Assert.notNull(searchQuery.getIndices(), "No index defined for Query"); 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 365ff1a65..60465751c 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 @@ -23,6 +23,7 @@ import org.springframework.data.elasticsearch.repository.query.parser.Elasticsea import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.ParametersParameterAccessor; import org.springframework.data.repository.query.parser.PartTree; +import org.springframework.util.ClassUtils; /** * ElasticsearchPartQuery @@ -46,7 +47,11 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery public Object execute(Object[] parameters) { ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters); CriteriaQuery query = createQuery(accessor); - if (queryMethod.isPageQuery()) { + if(tree.isDelete()) { + Object result = countOrGetDocumentsForDelete(query, accessor); + elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType()); + return result; + } else if (queryMethod.isPageQuery()) { query.setPageable(accessor.getPageable()); return elasticsearchOperations.queryForPage(query, queryMethod.getEntityInformation().getJavaType()); } else if (queryMethod.isCollectionQuery()) { @@ -63,6 +68,26 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType()); } + private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) { + + Object result = null; + + if (queryMethod.isCollectionQuery()) { + if (accessor.getPageable() == null) { + int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + query.setPageable(new PageRequest(0, Math.max(1, itemCount))); + } else { + query.setPageable(accessor.getPageable()); + } + result = elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType()); + } + + if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) { + result = elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType()); + } + return result; + } + public CriteriaQuery createQuery(ParametersParameterAccessor accessor) { return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery(); } 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 dcbaf9dc8..5b6278baf 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -559,6 +559,28 @@ public class ElasticsearchTemplateTests { assertThat(sampleEntity1, is(notNullValue())); } + @Test + public void shouldDeleteGivenCriteriaQuery() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntityBuilder(documentId).message("test message") + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class, true); + CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("message").contains("test")); + + // when + elasticsearchTemplate.delete(criteriaQuery, SampleEntity.class); + // then + StringQuery stringQuery = new StringQuery(matchAllQuery().toString()); + List sampleEntities = elasticsearchTemplate.queryForList(stringQuery, SampleEntity.class); + + assertThat(sampleEntities.size(), is(0)); + } + @Test public void shouldReturnSpecifiedFields() { // given diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java index 6582f52c3..009e5650f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/sample/SampleElasticsearchRepository.java @@ -15,6 +15,8 @@ */ package org.springframework.data.elasticsearch.repositories.sample; +import java.util.List; + import org.springframework.data.elasticsearch.entities.SampleEntity; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; @@ -24,4 +26,9 @@ import org.springframework.data.elasticsearch.repository.ElasticsearchRepository */ public interface SampleElasticsearchRepository extends ElasticsearchRepository { + long deleteById(String id); + List deleteByAvailable(boolean available); + List deleteByMessage(String message); + void deleteByType(String type); + } diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java index 1c40be1b7..3fae1d3cc 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepositoryTests.java @@ -299,6 +299,118 @@ public class SimpleElasticsearchRepositoryTests { assertThat(sampleEntities.getTotalElements(), equalTo(0L)); } + @Test + public void shouldDeleteById() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity = new SampleEntity(); + sampleEntity.setId(documentId); + sampleEntity.setMessage("hello world."); + sampleEntity.setVersion(System.currentTimeMillis()); + repository.save(sampleEntity); + // when + long result = repository.deleteById(documentId); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("id", documentId)).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(0L)); + assertThat(result, equalTo(1L)); + } + + @Test + public void shouldDeleteByMessageAndReturnList() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("hello world 1"); + sampleEntity1.setAvailable(true); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setMessage("hello world 2"); + sampleEntity2.setAvailable(true); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setMessage("hello world 3"); + sampleEntity3.setAvailable(false); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + List result = repository.deleteByAvailable(true); + // then + assertThat(result.size(), equalTo(2)); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(1L)); + } + + @Test + public void shouldDeleteByListForMessage() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setMessage("hello world 1"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setMessage("hello world 2"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setMessage("hello world 3"); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + List result = repository.deleteByMessage("hello world 3"); + // then + assertThat(result.size(), equalTo(1)); + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(2L)); + } + + @Test + public void shouldDeleteByType() { + // given + String documentId = randomNumeric(5); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(documentId); + sampleEntity1.setType("book"); + sampleEntity1.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(documentId); + sampleEntity2.setType("article"); + sampleEntity2.setVersion(System.currentTimeMillis()); + + documentId = randomNumeric(5); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(documentId); + sampleEntity3.setType("image"); + sampleEntity3.setVersion(System.currentTimeMillis()); + repository.save(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + // when + repository.deleteByType("article"); + // then + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build(); + Page sampleEntities = repository.search(searchQuery); + assertThat(sampleEntities.getTotalElements(), equalTo(2L)); + } + + + @Test public void shouldDeleteEntity() { // given