diff --git a/pom.xml b/pom.xml index 758725aa9..f672f02a9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-elasticsearch - 4.2.0-SNAPSHOT + 4.2.0-DATAES-976-SNAPSHOT org.springframework.data.build @@ -22,7 +22,7 @@ 7.9.3 2.13.3 4.1.52.Final - 2.5.0-SNAPSHOT + 2.4.0-DATACMNS-800-SNAPSHOT spring.data.elasticsearch 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 67b457ec0..e232f8cd1 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 @@ -66,6 +66,7 @@ * @author Murali Chevuri * @author Peter-Josef Meisch * @author Aleksei Arsenev + * @author Jens Schauder */ public class SimpleElasticsearchRepository implements ElasticsearchRepository { @@ -315,6 +316,31 @@ public void deleteAll(Iterable entities) { }); } + @Override + public void deleteAllById(Iterable ids) { + + Assert.notNull(ids, "Cannot delete 'null' list."); + + IndexCoordinates indexCoordinates = getIndexCoordinates(); + IdsQueryBuilder idsQueryBuilder = idsQuery(); + for (ID id : ids) { + 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, @Nullable String routing, IndexCoordinates indexCoordinates) { if (id != null) { 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 d136e26ec..85ea85268 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 @@ -35,12 +35,14 @@ import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.core.query.StringQuery; import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository; +import org.springframework.data.util.Streamable; import org.springframework.util.Assert; /** * @author Christoph Strobl * @author Peter-Josef Meisch * @author Aleksei Arsenev + * @author Jens Schauder * @since 3.2 */ public class SimpleReactiveElasticsearchRepository implements ReactiveElasticsearchRepository { @@ -52,7 +54,7 @@ public class SimpleReactiveElasticsearchRepository implements ReactiveEla private final ReactiveIndexOperations indexOperations; public SimpleReactiveElasticsearchRepository(ElasticsearchEntityInformation entityInformation, - ReactiveElasticsearchOperations operations) { + ReactiveElasticsearchOperations operations) { Assert.notNull(entityInformation, "EntityInformation must not be null!"); Assert.notNull(operations, "ElasticsearchOperations must not be null!"); @@ -211,6 +213,21 @@ public Mono deleteAll(Iterable entities) { return deleteAll(Flux.fromIterable(entities)); } + @Override + public Mono deleteAllById(Iterable ids) { + + Assert.notNull(ids, "Ids must not be null!"); + + return Mono.just(Streamable.of(ids) // + .map(this::convertId).toList() // + ).map(objects -> new StringQuery(QueryBuilders.idsQuery() // + .addIds(objects.toArray(new String[0])) // + .toString()) // + ).flatMap( + query -> operations.delete(query, entityInformation.getJavaType(), entityInformation.getIndexCoordinates())) // + .then(doRefresh()); + } + @Override public Mono deleteAll(Publisher entityStream) { diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java index 1203bea49..a6a0a432c 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepositoryTests.java @@ -15,6 +15,7 @@ */ package org.springframework.data.elasticsearch.repository.support; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.elasticsearch.annotations.FieldType.*; import static org.springframework.data.elasticsearch.core.query.Query.*; @@ -64,6 +65,7 @@ /** * @author Christoph Strobl * @author Peter-Josef Meisch + * @author Jens Schauder */ @SpringIntegrationTest @ContextConfiguration(classes = { SimpleReactiveElasticsearchRepositoryTests.Config.class }) @@ -107,7 +109,7 @@ private Mono documentWithIdExistsInIndex(String id) { public void saveShouldComputeMultipleEntities() { repository - .saveAll(Arrays.asList(SampleEntity.builder().build(), SampleEntity.builder().build(), + .saveAll(asList(SampleEntity.builder().build(), SampleEntity.builder().build(), SampleEntity.builder().build())) // .map(SampleEntity::getId) // .flatMap(this::documentWithIdExistsInIndex) // @@ -167,7 +169,7 @@ public void findAllShouldReturnAllElements() { @Test // DATAES-519 public void findAllByIdByIdShouldCompleteIfIndexDoesNotExist() { - repository.findAllById(Arrays.asList("id-two", "id-two")).as(StepVerifier::create).verifyComplete(); + repository.findAllById(asList("id-two", "id-two")).as(StepVerifier::create).verifyComplete(); } @Test // DATAES-519 @@ -178,7 +180,7 @@ public void findAllByIdShouldRetrieveMatchingDocuments() { SampleEntity.builder().id("id-three").build()) // .block(); - repository.findAllById(Arrays.asList("id-one", "id-two")) // + repository.findAllById(asList("id-one", "id-two")) // .as(StepVerifier::create)// .expectNextMatches(entity -> entity.getId().equals("id-one") || entity.getId().equals("id-two")) // .expectNextMatches(entity -> entity.getId().equals("id-one") || entity.getId().equals("id-two")) // @@ -193,7 +195,7 @@ public void findAllByIdShouldCompleteWhenNothingFound() { SampleEntity.builder().id("id-three").build()) // .block(); - repository.findAllById(Arrays.asList("can't", "touch", "this")) // + repository.findAllById(asList("can't", "touch", "this")) // .as(StepVerifier::create)// .verifyComplete(); } @@ -380,6 +382,18 @@ public void deleteByIdShouldDeleteEntry() { assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse(); } + @Test // DATAES-976 + public void deleteAllByIdShouldDeleteEntry() { + + SampleEntity toBeDeleted = SampleEntity.builder().id("id-two").build(); + bulkIndex(SampleEntity.builder().id("id-one").build(), toBeDeleted) // + .block(); + + repository.deleteAllById(asList(toBeDeleted.getId())).as(StepVerifier::create).verifyComplete(); + + assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse(); + } + @Test // DATAES-519 public void deleteShouldDeleteEntry() { @@ -402,7 +416,7 @@ public void deleteAllShouldDeleteGivenEntries() { bulkIndex(toBeDeleted, hangInThere, toBeDeleted2) // .block(); - repository.deleteAll(Arrays.asList(toBeDeleted, toBeDeleted2)).as(StepVerifier::create).verifyComplete(); + repository.deleteAll(asList(toBeDeleted, toBeDeleted2)).as(StepVerifier::create).verifyComplete(); assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse(); assertThat(documentWithIdExistsInIndex(toBeDeleted2.getId()).block()).isFalse(); @@ -547,7 +561,7 @@ public void derivedDeleteMethodShouldBeExecutedCorrectly() { } Mono bulkIndex(SampleEntity... entities) { - return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(INDEX)).then(); + return operations.saveAll(asList(entities), IndexCoordinates.of(INDEX)).then(); } interface ReactiveSampleEntityRepository extends ReactiveCrudRepository { diff --git a/src/test/java/org/springframework/data/elasticsearch/repository/support/simple/SimpleElasticsearchRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/repository/support/simple/SimpleElasticsearchRepositoryIntegrationTests.java index 9205aa49e..75e67274a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repository/support/simple/SimpleElasticsearchRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repository/support/simple/SimpleElasticsearchRepositoryIntegrationTests.java @@ -406,6 +406,40 @@ public void shouldDeleteById() { assertThat(result).isEqualTo(1L); } + @Test //DATAES-976 + public void shouldDeleteAllById() { + + // given + String id1 = nextIdAsString(); + SampleEntity sampleEntity1 = new SampleEntity(); + sampleEntity1.setId(id1); + sampleEntity1.setMessage("hello world 1"); + sampleEntity1.setAvailable(true); + sampleEntity1.setVersion(System.currentTimeMillis()); + + String id2 = nextIdAsString(); + SampleEntity sampleEntity2 = new SampleEntity(); + sampleEntity2.setId(id2); + sampleEntity2.setMessage("hello world 2"); + sampleEntity2.setAvailable(true); + sampleEntity2.setVersion(System.currentTimeMillis()); + + String id3 = nextIdAsString(); + SampleEntity sampleEntity3 = new SampleEntity(); + sampleEntity3.setId(id3); + sampleEntity3.setMessage("hello world 3"); + sampleEntity3.setAvailable(false); + sampleEntity3.setVersion(System.currentTimeMillis()); + + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + // when + repository.deleteAllById(Arrays.asList(id1, id3)); + + // then + assertThat(repository.findAll()).extracting(SampleEntity::getId).containsExactly(id2); + } + @Test public void shouldDeleteByMessageAndReturnList() {