Skip to content

Commit c77b543

Browse files
Ivan Greenexhaggi
authored andcommitted
DATAES-523 - Allow specifying version type.
Allow specifying the version type for documents. Original pull request: spring-projects#236
1 parent ae1accd commit c77b543

File tree

10 files changed

+161
-8
lines changed

10 files changed

+161
-8
lines changed

src/main/java/org/springframework/data/elasticsearch/annotations/Document.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.lang.annotation.*;
1919

20+
import org.elasticsearch.index.VersionType;
2021
import org.springframework.data.annotation.Persistent;
2122

2223
/**
@@ -25,6 +26,7 @@
2526
* @author Rizwan Idrees
2627
* @author Mohsin Husen
2728
* @author Mason Chan
29+
* @author Ivan Greene
2830
*/
2931

3032
@Persistent
@@ -48,4 +50,6 @@
4850
String indexStoreType() default "fs";
4951

5052
boolean createIndex() default true;
53+
54+
VersionType versionType() default VersionType.EXTERNAL;
5155
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package org.springframework.data.elasticsearch.core;
1717

1818
import static org.elasticsearch.client.Requests.refreshRequest;
19-
import static org.elasticsearch.index.VersionType.EXTERNAL;
2019
import static org.elasticsearch.index.query.QueryBuilders.moreLikeThisQuery;
2120
import static org.elasticsearch.index.query.QueryBuilders.wrapperQuery;
2221
import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMapping;
@@ -67,6 +66,7 @@
6766
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
6867
import org.elasticsearch.common.xcontent.XContentBuilder;
6968
import org.elasticsearch.common.xcontent.XContentType;
69+
import org.elasticsearch.index.VersionType;
7070
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
7171
import org.elasticsearch.index.query.QueryBuilder;
7272
import org.elasticsearch.index.query.QueryBuilders;
@@ -131,6 +131,7 @@
131131
* @author Don Wellington
132132
* @author Zetang Zeng
133133
* @author Peter Nowak
134+
* @author Ivan Greene
134135
*/
135136
public class ElasticsearchRestTemplate
136137
implements ElasticsearchOperations, EsClient<RestHighLevelClient>, ApplicationContextAware {
@@ -1343,7 +1344,8 @@ private IndexRequest prepareIndex(IndexQuery query) {
13431344
}
13441345
if (query.getVersion() != null) {
13451346
indexRequest.version(query.getVersion());
1346-
indexRequest.versionType(EXTERNAL);
1347+
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
1348+
indexRequest.versionType(versionType);
13471349
}
13481350

13491351
if (query.getParentId() != null) {
@@ -1520,6 +1522,13 @@ private String[] retrieveTypeFromPersistentEntity(Class clazz) {
15201522
return null;
15211523
}
15221524

1525+
private VersionType retrieveVersionTypeFromPersistentEntity(Class clazz) {
1526+
if (clazz != null) {
1527+
return getPersistentEntityFor(clazz).getVersionType();
1528+
}
1529+
return VersionType.EXTERNAL;
1530+
}
1531+
15231532
private List<String> extractIds(SearchResponse response) {
15241533
List<String> ids = new ArrayList<>();
15251534
for (SearchHit hit : response.getHits()) {

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package org.springframework.data.elasticsearch.core;
1717

1818
import static org.elasticsearch.client.Requests.*;
19-
import static org.elasticsearch.index.VersionType.*;
2019
import static org.elasticsearch.index.query.QueryBuilders.*;
2120
import static org.springframework.data.elasticsearch.core.MappingBuilder.*;
2221
import static org.springframework.util.CollectionUtils.*;
@@ -65,6 +64,7 @@
6564
import org.elasticsearch.common.unit.TimeValue;
6665
import org.elasticsearch.common.xcontent.XContentBuilder;
6766
import org.elasticsearch.common.xcontent.XContentType;
67+
import org.elasticsearch.index.VersionType;
6868
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
6969
import org.elasticsearch.index.query.QueryBuilder;
7070
import org.elasticsearch.index.query.QueryBuilders;
@@ -137,6 +137,7 @@
137137
* @author Ted Liang
138138
* @author Jean-Baptiste Nizet
139139
* @author Zetang Zeng
140+
* @author Ivan Greene
140141
*/
141142
public class ElasticsearchTemplate implements ElasticsearchOperations, EsClient<Client>, ApplicationContextAware {
142143

@@ -1175,7 +1176,8 @@ private IndexRequestBuilder prepareIndex(IndexQuery query) {
11751176
}
11761177
if (query.getVersion() != null) {
11771178
indexRequestBuilder.setVersion(query.getVersion());
1178-
indexRequestBuilder.setVersionType(EXTERNAL);
1179+
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
1180+
indexRequestBuilder.setVersionType(versionType);
11791181
}
11801182

11811183
if (query.getParentId() != null) {
@@ -1288,6 +1290,13 @@ private String[] retrieveTypeFromPersistentEntity(Class clazz) {
12881290
return null;
12891291
}
12901292

1293+
private VersionType retrieveVersionTypeFromPersistentEntity(Class clazz) {
1294+
if (clazz != null) {
1295+
return getPersistentEntityFor(clazz).getVersionType();
1296+
}
1297+
return VersionType.EXTERNAL;
1298+
}
1299+
12911300
private List<String> extractIds(SearchResponse response) {
12921301
List<String> ids = new ArrayList<>();
12931302
for (SearchHit hit : response.getHits()) {

src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core.mapping;
1717

18+
import org.elasticsearch.index.VersionType;
1819
import org.springframework.data.mapping.PersistentEntity;
1920
import org.springframework.lang.Nullable;
2021

@@ -26,6 +27,7 @@
2627
* @author Mark Paluch
2728
* @author Sascha Woo
2829
* @author Oliver Gierke
30+
* @author Ivan Greene
2931
*/
3032
public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> {
3133

@@ -51,6 +53,8 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
5153

5254
String settingPath();
5355

56+
VersionType getVersionType();
57+
5458
boolean isCreateIndexAndMapping();
5559

5660
/**

src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Locale;
2121

22+
import org.elasticsearch.index.VersionType;
2223
import org.springframework.beans.BeansException;
2324
import org.springframework.context.ApplicationContext;
2425
import org.springframework.context.ApplicationContextAware;
@@ -28,7 +29,6 @@
2829
import org.springframework.data.elasticsearch.annotations.Parent;
2930
import org.springframework.data.elasticsearch.annotations.Setting;
3031
import org.springframework.data.mapping.MappingException;
31-
import org.springframework.data.mapping.PersistentPropertyAccessor;
3232
import org.springframework.data.mapping.model.BasicPersistentEntity;
3333
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
3434
import org.springframework.data.util.TypeInformation;
@@ -47,6 +47,7 @@
4747
* @author Mohsin Husen
4848
* @author Mark Paluch
4949
* @author Sascha Woo
50+
* @author Ivan Greene
5051
*/
5152
public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty>
5253
implements ElasticsearchPersistentEntity<T>, ApplicationContextAware {
@@ -65,6 +66,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
6566
private ElasticsearchPersistentProperty parentIdProperty;
6667
private ElasticsearchPersistentProperty scoreProperty;
6768
private String settingPath;
69+
private VersionType versionType;
6870
private boolean createIndexAndMapping;
6971

7072
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
@@ -84,6 +86,7 @@ public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
8486
this.replicas = document.replicas();
8587
this.refreshInterval = document.refreshInterval();
8688
this.indexStoreType = document.indexStoreType();
89+
this.versionType = document.versionType();
8790
this.createIndexAndMapping = document.createIndex();
8891
}
8992
if (clazz.isAnnotationPresent(Setting.class)) {
@@ -155,6 +158,11 @@ public ElasticsearchPersistentProperty getParentIdProperty() {
155158
return parentIdProperty;
156159
}
157160

161+
@Override
162+
public VersionType getVersionType() {
163+
return versionType;
164+
}
165+
158166
@Override
159167
public String settingPath() {
160168
return settingPath;

src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.repository.support;
1717

18+
import org.elasticsearch.index.VersionType;
1819
import org.springframework.data.repository.core.EntityInformation;
1920

2021
/**
@@ -23,6 +24,7 @@
2324
* @author Rizwan Idrees
2425
* @author Mohsin Husen
2526
* @author Christoph Strobl
27+
* @author Ivan Greene
2628
*/
2729
public interface ElasticsearchEntityInformation<T, ID> extends EntityInformation<T, ID> {
2830

@@ -34,5 +36,7 @@ public interface ElasticsearchEntityInformation<T, ID> extends EntityInformation
3436

3537
Long getVersion(T entity);
3638

39+
VersionType getVersionType();
40+
3741
String getParentId(T entity);
3842
}

src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.repository.support;
1717

18+
import org.elasticsearch.index.VersionType;
1819
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
1920
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
2021
import org.springframework.data.repository.core.support.PersistentEntityInformation;
@@ -32,19 +33,21 @@
3233
* @author Oliver Gierke
3334
* @author Mark Paluch
3435
* @author Christoph Strobl
36+
* @author Ivan Greene
3537
*/
3638
public class MappingElasticsearchEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
3739
implements ElasticsearchEntityInformation<T, ID> {
3840

3941
private final ElasticsearchPersistentEntity<T> entityMetadata;
4042
private final String indexName;
4143
private final String type;
44+
private final VersionType versionType;
4245

4346
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity) {
44-
this(entity, entity.getIndexName(), entity.getIndexType());
47+
this(entity, entity.getIndexName(), entity.getIndexType(), entity.getVersionType());
4548
}
4649

47-
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity, String indexName, String type) {
50+
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity, String indexName, String type, VersionType versionType) {
4851
super(entity);
4952

5053
Assert.notNull(indexName, "IndexName must not be null!");
@@ -53,6 +56,7 @@ public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> en
5356
this.entityMetadata = entity;
5457
this.indexName = indexName;
5558
this.type = type;
59+
this.versionType = versionType;
5660
}
5761

5862
@Override
@@ -81,6 +85,11 @@ public Long getVersion(T entity) {
8185
}
8286
}
8387

88+
@Override
89+
public VersionType getVersionType() {
90+
return versionType;
91+
}
92+
8493
@Override
8594
public String getParentId(T entity) {
8695

src/main/java/org/springframework/data/elasticsearch/repository/support/ReactiveElasticsearchRepositoryFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
* instances.
4848
*
4949
* @author Christoph Strobl
50+
* @author Ivan Greene
5051
* @since 3.2
5152
*/
5253
public class ReactiveElasticsearchRepositoryFactory extends ReactiveRepositoryFactorySupport {
@@ -116,7 +117,7 @@ private <T, ID> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class
116117
ElasticsearchPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
117118

118119
return new MappingElasticsearchEntityInformation<>((ElasticsearchPersistentEntity<T>) entity, entity.getIndexName(),
119-
entity.getIndexType());
120+
entity.getIndexType(), entity.getVersionType());
120121
}
121122

122123
/**

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
5454
import org.springframework.data.elasticsearch.core.query.*;
5555
import org.springframework.data.elasticsearch.entities.Book;
56+
import org.springframework.data.elasticsearch.entities.GTEVersionEntity;
5657
import org.springframework.data.elasticsearch.entities.HetroEntity1;
5758
import org.springframework.data.elasticsearch.entities.HetroEntity2;
5859
import org.springframework.data.elasticsearch.entities.SampleEntity;
@@ -80,6 +81,7 @@
8081
* @author Jean-Baptiste Nizet
8182
* @author Zetang Zeng
8283
* @author Peter Nowak
84+
* @author Ivan Greene
8385
*/
8486

8587
@Ignore
@@ -1814,6 +1816,60 @@ public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz,
18141816
assertThat(sampleEntities.getContent().get(1).get("userId"), is(person2.get("userId")));
18151817
}
18161818

1819+
/*
1820+
DATAES-523
1821+
*/
1822+
@Test
1823+
public void shouldIndexGteEntityWithVersionType() {
1824+
// given
1825+
String documentId = randomNumeric(5);
1826+
GTEVersionEntity entity = GTEVersionEntity.builder().id(documentId)
1827+
.name("FooBar")
1828+
.version(System.currentTimeMillis()).build();
1829+
1830+
IndexQueryBuilder indexQueryBuilder = new IndexQueryBuilder().withId(documentId)
1831+
.withIndexName(INDEX_NAME).withType(TYPE_NAME)
1832+
.withVersion(entity.getVersion())
1833+
.withObject(entity);
1834+
1835+
Exception ex = null;
1836+
1837+
try {
1838+
elasticsearchTemplate.index(indexQueryBuilder.build());
1839+
} catch (Exception e) {
1840+
ex = e;
1841+
}
1842+
assertNull(ex);
1843+
elasticsearchTemplate.refresh(INDEX_NAME);
1844+
1845+
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(INDEX_NAME)
1846+
.withTypes(TYPE_NAME).withQuery(matchAllQuery()).build();
1847+
// when
1848+
Page<GTEVersionEntity> entities = elasticsearchTemplate.queryForPage(searchQuery, GTEVersionEntity.class);
1849+
// then
1850+
assertThat(entities, is(notNullValue()));
1851+
assertThat(entities.getTotalElements(), greaterThanOrEqualTo(1L));
1852+
1853+
// reindex with same version
1854+
try {
1855+
elasticsearchTemplate.index(indexQueryBuilder.build());
1856+
} catch (Exception e) {
1857+
ex = e;
1858+
}
1859+
assertNull(ex);
1860+
elasticsearchTemplate.refresh(INDEX_NAME);
1861+
1862+
// reindex with version one below
1863+
try {
1864+
elasticsearchTemplate.index(indexQueryBuilder.withVersion(entity.getVersion() - 1).build());
1865+
} catch (Exception e) {
1866+
ex = e;
1867+
}
1868+
assertNotNull(ex);
1869+
String message = ex.getMessage().toLowerCase();
1870+
assertTrue("Exception is version conflict", message.contains("version") && message.contains("conflict"));
1871+
}
1872+
18171873
@Test
18181874
public void shouldIndexSampleEntityWithIndexAndTypeAtRuntime() {
18191875
// given

0 commit comments

Comments
 (0)