From 5c582d3e0da4f58809be17a39b76c6208f861ca8 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Nov 2020 14:00:18 +0100 Subject: [PATCH 1/3] DATAES-976 - Prepare branch --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From d9cb5a93a68052492f7aae935fe3e50ae3a440e7 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Nov 2020 15:20:22 +0100 Subject: [PATCH 2/3] DATAES-976 - Implement CrudRepository.delete(Iterable ids). --- .../SimpleElasticsearchRepository.java | 26 ++++++++++ ...SimpleReactiveElasticsearchRepository.java | 19 ++++++- ...eReactiveElasticsearchRepositoryTests.java | 26 +++++++--- ...asticsearchRepositoryIntegrationTests.java | 52 ++++++++++++++++--- 4 files changed, 108 insertions(+), 15 deletions(-) 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..298ae6f97 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 @@ -15,6 +15,7 @@ */ package org.springframework.data.elasticsearch.repository.support.simple; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.elasticsearch.index.query.QueryBuilders.*; import static org.springframework.data.elasticsearch.annotations.FieldType.*; @@ -73,6 +74,7 @@ * @author Michael Wirth * @author Peter-Josef Meisch * @author Murali Chevuri + * @author Jens Schauder */ @SpringIntegrationTest @ContextConfiguration(classes = { SimpleElasticsearchRepositoryIntegrationTests.Config.class }) @@ -118,7 +120,7 @@ public void shouldDoBulkIndexDocument() { sampleEntity2.setVersion(System.currentTimeMillis()); // when - repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2)); + repository.saveAll(asList(sampleEntity1, sampleEntity2)); // then Optional entity1FromElasticSearch = repository.findById(documentId1); @@ -283,7 +285,7 @@ public void shouldFindAllByIdQuery() { repository.save(sampleEntity2); // when - Iterable sampleEntities = repository.findAllById(Arrays.asList(documentId, documentId2)); + Iterable sampleEntities = repository.findAllById(asList(documentId, documentId2)); // then assertThat(sampleEntities).isNotNull().hasSize(2); @@ -305,7 +307,7 @@ public void shouldSaveIterableEntities() { sampleEntity2.setMessage("hello world."); sampleEntity2.setVersion(System.currentTimeMillis()); - Iterable sampleEntities = Arrays.asList(sampleEntity1, sampleEntity2); + Iterable sampleEntities = asList(sampleEntity1, sampleEntity2); // when repository.saveAll(sampleEntities); @@ -406,6 +408,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(asList(sampleEntity1, sampleEntity2, sampleEntity3)); + + // when + repository.deleteAllById(asList(id1, id3)); + + // then + assertThat(repository.findAll()).extracting(SampleEntity::getId).containsExactly(id2); + } + @Test public void shouldDeleteByMessageAndReturnList() { @@ -430,7 +466,7 @@ public void shouldDeleteByMessageAndReturnList() { sampleEntity3.setMessage("hello world 3"); sampleEntity3.setAvailable(false); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when List result = repository.deleteByAvailable(true); @@ -463,7 +499,7 @@ public void shouldDeleteByListForMessage() { sampleEntity3.setId(documentId); sampleEntity3.setMessage("hello world 3"); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when List result = repository.deleteByMessage("hello world 3"); @@ -496,7 +532,7 @@ public void shouldDeleteByType() { sampleEntity3.setId(documentId); sampleEntity3.setType("image"); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when repository.deleteByType("article"); @@ -569,7 +605,7 @@ public void shouldDeleteIterableEntities() { sampleEntity2.setVersion(System.currentTimeMillis()); repository.save(sampleEntity2); - Iterable sampleEntities = Arrays.asList(sampleEntity2, sampleEntity2); + Iterable sampleEntities = asList(sampleEntity2, sampleEntity2); // when repository.deleteAll(sampleEntities); @@ -710,7 +746,7 @@ void shouldNotReturnNullValuesInFindAllById() throws IOException { repository.save(sampleEntity3); Iterable allById = repository - .findAllById(Arrays.asList("id-one", "does-not-exist", "id-two", "where-am-i", "id-three")); + .findAllById(asList("id-one", "does-not-exist", "id-two", "where-am-i", "id-three")); List results = StreamUtils.createStreamFromIterator(allById.iterator()).collect(Collectors.toList()); assertThat(results).hasSize(3); From a570b63e45b8f0b6074f62b3876d907703ed2a1e Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 24 Nov 2020 16:08:05 +0100 Subject: [PATCH 3/3] DATAES-976 - Undo the import of java.util.Arrays.*. --- ...asticsearchRepositoryIntegrationTests.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) 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 298ae6f97..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 @@ -15,7 +15,6 @@ */ package org.springframework.data.elasticsearch.repository.support.simple; -import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.elasticsearch.index.query.QueryBuilders.*; import static org.springframework.data.elasticsearch.annotations.FieldType.*; @@ -74,7 +73,6 @@ * @author Michael Wirth * @author Peter-Josef Meisch * @author Murali Chevuri - * @author Jens Schauder */ @SpringIntegrationTest @ContextConfiguration(classes = { SimpleElasticsearchRepositoryIntegrationTests.Config.class }) @@ -120,7 +118,7 @@ public void shouldDoBulkIndexDocument() { sampleEntity2.setVersion(System.currentTimeMillis()); // when - repository.saveAll(asList(sampleEntity1, sampleEntity2)); + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2)); // then Optional entity1FromElasticSearch = repository.findById(documentId1); @@ -285,7 +283,7 @@ public void shouldFindAllByIdQuery() { repository.save(sampleEntity2); // when - Iterable sampleEntities = repository.findAllById(asList(documentId, documentId2)); + Iterable sampleEntities = repository.findAllById(Arrays.asList(documentId, documentId2)); // then assertThat(sampleEntities).isNotNull().hasSize(2); @@ -307,7 +305,7 @@ public void shouldSaveIterableEntities() { sampleEntity2.setMessage("hello world."); sampleEntity2.setVersion(System.currentTimeMillis()); - Iterable sampleEntities = asList(sampleEntity1, sampleEntity2); + Iterable sampleEntities = Arrays.asList(sampleEntity1, sampleEntity2); // when repository.saveAll(sampleEntities); @@ -433,10 +431,10 @@ public void shouldDeleteAllById() { sampleEntity3.setAvailable(false); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when - repository.deleteAllById(asList(id1, id3)); + repository.deleteAllById(Arrays.asList(id1, id3)); // then assertThat(repository.findAll()).extracting(SampleEntity::getId).containsExactly(id2); @@ -466,7 +464,7 @@ public void shouldDeleteByMessageAndReturnList() { sampleEntity3.setMessage("hello world 3"); sampleEntity3.setAvailable(false); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when List result = repository.deleteByAvailable(true); @@ -499,7 +497,7 @@ public void shouldDeleteByListForMessage() { sampleEntity3.setId(documentId); sampleEntity3.setMessage("hello world 3"); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when List result = repository.deleteByMessage("hello world 3"); @@ -532,7 +530,7 @@ public void shouldDeleteByType() { sampleEntity3.setId(documentId); sampleEntity3.setType("image"); sampleEntity3.setVersion(System.currentTimeMillis()); - repository.saveAll(asList(sampleEntity1, sampleEntity2, sampleEntity3)); + repository.saveAll(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when repository.deleteByType("article"); @@ -605,7 +603,7 @@ public void shouldDeleteIterableEntities() { sampleEntity2.setVersion(System.currentTimeMillis()); repository.save(sampleEntity2); - Iterable sampleEntities = asList(sampleEntity2, sampleEntity2); + Iterable sampleEntities = Arrays.asList(sampleEntity2, sampleEntity2); // when repository.deleteAll(sampleEntities); @@ -746,7 +744,7 @@ void shouldNotReturnNullValuesInFindAllById() throws IOException { repository.save(sampleEntity3); Iterable allById = repository - .findAllById(asList("id-one", "does-not-exist", "id-two", "where-am-i", "id-three")); + .findAllById(Arrays.asList("id-one", "does-not-exist", "id-two", "where-am-i", "id-three")); List results = StreamUtils.createStreamFromIterator(allById.iterator()).collect(Collectors.toList()); assertThat(results).hasSize(3);