Skip to content

Commit 7e904cd

Browse files
authored
Support partially update document by entity.
Original Pull Request #2305 Closes #2304
1 parent e46b497 commit 7e904cd

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

CONTRIBUTING.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ In order to run the tests locally with `./mvnw test` you need to have docker run
88

99
== Class names of the test classes
1010

11-
Tset classes that do depend on the client have either `ERHLC` (when using the deprecated Elasticsearch `RestHighLevelClient`) or `ELC` (the new `ElasticsearchClient`) in their name.
11+
Test classes that do depend on the client have either `ERHLC` (when using the deprecated Elasticsearch `RestHighLevelClient`) or `ELC` (the new `ElasticsearchClient`) in their name.

src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.springframework.data.elasticsearch.core.query.Query;
4949
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
5050
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
51+
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
5152
import org.springframework.data.elasticsearch.core.routing.DefaultRoutingResolver;
5253
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
5354
import org.springframework.data.elasticsearch.support.VersionInfo;
@@ -74,6 +75,7 @@
7475
* @author Subhobrata Dey
7576
* @author Steven Pearce
7677
* @author Anton Naydenov
78+
* @author Haibo Liu
7779
*/
7880
public abstract class AbstractElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
7981

@@ -305,7 +307,7 @@ public String delete(Object entity) {
305307
@Override
306308
public String delete(Object entity, IndexCoordinates index) {
307309
String entityId = getEntityId(entity);
308-
Assert.notNull(entityId, "entity must have an if that is notnull");
310+
Assert.notNull(entityId, "entity must have an id that is notnull");
309311
return this.delete(entityId, index);
310312
}
311313

@@ -468,6 +470,25 @@ public IndexCoordinates getIndexCoordinatesFor(Class<?> clazz) {
468470
return getRequiredPersistentEntity(clazz).getIndexCoordinates();
469471
}
470472

473+
@Override
474+
public <T> UpdateResponse update(T entity) {
475+
return update(this.buildUpdateQueryByEntity(entity), this.getIndexCoordinatesFor(entity.getClass()));
476+
}
477+
478+
protected <T> UpdateQuery buildUpdateQueryByEntity(T entity) {
479+
String id = this.getEntityId(entity);
480+
Assert.notNull(entity, "entity must have an id that is notnull");
481+
482+
UpdateQuery.Builder updateQueryBuilder = UpdateQuery.builder(id)
483+
.withDocument(elasticsearchConverter.mapObject(entity));
484+
485+
String routing = this.getEntityRouting(entity);
486+
if (Objects.nonNull(routing)) {
487+
updateQueryBuilder.withRouting(routing);
488+
}
489+
return updateQueryBuilder.build();
490+
}
491+
471492
protected <T> T updateIndexedObject(T entity, IndexedObjectInformation indexedObjectInformation) {
472493

473494
ElasticsearchPersistentEntity<?> persistentEntity = elasticsearchConverter.getMappingContext()
@@ -508,7 +529,7 @@ ElasticsearchPersistentEntity<?> getRequiredPersistentEntity(Class<?> clazz) {
508529
}
509530

510531
@Nullable
511-
private String getEntityId(Object entity) {
532+
public String getEntityId(Object entity) {
512533

513534
Object id = entityOperations.forEntity(entity, elasticsearchConverter.getConversionService(), routingResolver)
514535
.getId();

src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @author Peter-Josef Meisch
3838
* @author Farid Faoudi
3939
* @author Sijia Liu
40+
* @author Haibo Liu
4041
* @since 4.0
4142
*/
4243
public interface DocumentOperations {
@@ -307,6 +308,15 @@ default void bulkUpdate(List<UpdateQuery> queries, IndexCoordinates index) {
307308
*/
308309
ByQueryResponse delete(Query query, Class<?> clazz, IndexCoordinates index);
309310

311+
/**
312+
* Partially update a document by the given entity.
313+
*
314+
* @param entity the entity to update partially
315+
* @return the update response
316+
* @param <T> the entity type
317+
*/
318+
<T> UpdateResponse update(T entity);
319+
310320
/**
311321
* Partial update of the document.
312322
*

src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchIntegrationTests.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
* @author Farid Faoudi
106106
* @author Peer Mueller
107107
* @author Sijia Liu
108+
* @author Haibo Liu
108109
*/
109110
@SpringIntegrationTest
110111
public abstract class ElasticsearchIntegrationTests implements NewElasticsearchClientDevelopment {
@@ -177,6 +178,20 @@ protected abstract Query getMatchAllQueryWithIncludesAndInlineExpressionScript(@
177178

178179
protected abstract Query getQueryWithRescorer();
179180

181+
@Test
182+
public void shouldThrowDataAccessExceptionIfDocumentDoesNotExistWhileDoingPartialUpdateByEntity() {
183+
184+
// given
185+
String documentId = nextIdAsString();
186+
String messageBeforeUpdate = "some test message";
187+
188+
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(messageBeforeUpdate)
189+
.version(System.currentTimeMillis()).build();
190+
191+
assertThatThrownBy(() -> operations.update(sampleEntity))
192+
.isInstanceOf(DataAccessException.class);
193+
}
194+
180195
@Test
181196
public void shouldThrowDataAccessExceptionIfDocumentDoesNotExistWhileDoingPartialUpdate() {
182197

@@ -1499,6 +1514,33 @@ public void shouldDeleteIndexForGivenEntity() {
14991514
assertThat(indexOperations.exists()).isFalse();
15001515
}
15011516

1517+
@Test
1518+
public void shouldDoPartialUpdateBySuppliedEntityForExistingDocument() {
1519+
1520+
// given
1521+
String documentId = nextIdAsString();
1522+
String messageBeforeUpdate = "some test message";
1523+
String messageAfterUpdate = "test message";
1524+
1525+
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(messageBeforeUpdate)
1526+
.version(System.currentTimeMillis()).build();
1527+
1528+
IndexQuery indexQuery = getIndexQuery(sampleEntity);
1529+
1530+
operations.index(indexQuery, IndexCoordinates.of(indexNameProvider.indexName()));
1531+
1532+
// modify the entity
1533+
sampleEntity.setMessage(messageAfterUpdate);
1534+
1535+
// when
1536+
operations.update(sampleEntity);
1537+
1538+
// then
1539+
SampleEntity indexedEntity = operations.get(documentId, SampleEntity.class,
1540+
IndexCoordinates.of(indexNameProvider.indexName()));
1541+
assertThat(indexedEntity.getMessage()).isEqualTo(messageAfterUpdate);
1542+
}
1543+
15021544
@Test
15031545
public void shouldDoPartialUpdateForExistingDocument() {
15041546

0 commit comments

Comments
 (0)