Skip to content

Commit eae9992

Browse files
committed
Support serialization for DynamicTemplates.
Signed-off-by: Youssef Aouichaoui <[email protected]>
1 parent d079a59 commit eae9992

File tree

6 files changed

+77
-2
lines changed

6 files changed

+77
-2
lines changed

Diff for: src/main/java/org/springframework/data/elasticsearch/annotations/Field.java

+7
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,11 @@
248248
* @since 5.4
249249
*/
250250
String mappedTypeName() default "";
251+
252+
/**
253+
* Maps your data beyond the dynamic field mapping rules.
254+
*
255+
* @since 5.4
256+
*/
257+
boolean dynamicTemplate() default false;
251258
}

Diff for: src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,14 @@ protected void writeProperty(ElasticsearchPersistentProperty property, Object va
10351035

10361036
if (valueType.isMap()) {
10371037
Map<String, Object> mapDbObj = createMap((Map<?, ?>) value, property);
1038-
sink.set(property, mapDbObj);
1038+
if (property.isDynamicFieldMapping()) {
1039+
for (Entry<String, Object> entry : mapDbObj.entrySet()) {
1040+
sink.set(entry.getKey(), entry.getValue());
1041+
}
1042+
} else {
1043+
sink.set(property, mapDbObj);
1044+
}
1045+
10391046
return;
10401047
}
10411048

@@ -1499,7 +1506,11 @@ public void set(ElasticsearchPersistentProperty property, @Nullable Object value
14991506
}
15001507
}
15011508

1502-
target.put(property.getFieldName(), value);
1509+
set(property.getFieldName(), value);
1510+
}
1511+
1512+
public void set(String key, @Nullable Object value) {
1513+
target.put(key, value);
15031514
}
15041515

15051516
private Map<String, Object> getAsMap(Object result) {

Diff for: src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java

+7
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
110110
*/
111111
boolean isIndexedIndexNameProperty();
112112

113+
/**
114+
* Maps your data beyond the dynamic field mapping rules.
115+
*
116+
* @since 5.4
117+
*/
118+
boolean isDynamicFieldMapping();
119+
113120
/**
114121
* calls {@link #getActualType()} but returns null when an exception is thrown
115122
*

Diff for: src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java

+7
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public class SimpleElasticsearchPersistentProperty extends
8686
@Nullable private PropertyValueConverter propertyValueConverter;
8787
private final boolean storeNullValue;
8888
private final boolean storeEmptyValue;
89+
private final boolean isDynamicFieldMapping;
8990

9091
public SimpleElasticsearchPersistentProperty(Property property,
9192
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
@@ -111,6 +112,7 @@ public SimpleElasticsearchPersistentProperty(Property property,
111112

112113
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
113114
storeEmptyValue = isField ? getRequiredAnnotation(Field.class).storeEmptyValue() : true;
115+
isDynamicFieldMapping = isField && getRequiredAnnotation(Field.class).dynamicTemplate();
114116
}
115117

116118
@Override
@@ -390,4 +392,9 @@ public boolean isCompletionProperty() {
390392
public boolean isIndexedIndexNameProperty() {
391393
return isAnnotationPresent(IndexedIndexName.class);
392394
}
395+
396+
@Override
397+
public boolean isDynamicFieldMapping() {
398+
return isDynamicFieldMapping;
399+
}
393400
}

Diff for: src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java

+31
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
package org.springframework.data.elasticsearch.core.index;
1818

19+
import static java.util.UUID.randomUUID;
1920
import static org.assertj.core.api.Assertions.*;
2021
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
22+
import static org.springframework.data.elasticsearch.core.query.StringQuery.MATCH_ALL;
2123

2224
import java.time.Instant;
2325
import java.time.LocalDate;
@@ -40,7 +42,9 @@
4042
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
4143
import org.springframework.data.elasticsearch.core.IndexOperations;
4244
import org.springframework.data.elasticsearch.core.MappingContextBaseTests;
45+
import org.springframework.data.elasticsearch.core.SearchHits;
4346
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
47+
import org.springframework.data.elasticsearch.core.query.StringQuery;
4448
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
4549
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
4650
import org.springframework.lang.Nullable;
@@ -280,6 +284,24 @@ void shouldWriteMappingWithFieldAliases() {
280284
operations.indexOps(FieldAliasEntity.class).createWithMapping();
281285
}
282286

287+
@Test
288+
void shouldMapDynamicFields() {
289+
// Given
290+
IndexOperations documentOperations = operations.indexOps(DynamicFieldDocument.class);
291+
documentOperations.createWithMapping();
292+
293+
DynamicFieldDocument document = new DynamicFieldDocument();
294+
document.dynamicFields = Map.of("a_str", randomUUID().toString(), "b_str", randomUUID().toString());
295+
operations.save(document);
296+
297+
// When
298+
SearchHits<DynamicFieldDocument> results = operations.search(new StringQuery(MATCH_ALL), DynamicFieldDocument.class);
299+
300+
// Then
301+
assertThat(results.getTotalHits()).isEqualTo(1);
302+
documentOperations.delete();
303+
}
304+
283305
// region Entities
284306
@Document(indexName = "#{@indexNameProvider.indexName()}")
285307
static class Book {
@@ -933,5 +955,14 @@ private static class FieldAliasEntity {
933955
@Field(type = Text) private String otherText;
934956
}
935957

958+
@SuppressWarnings("unused")
959+
@Document(indexName = "foo")
960+
@DynamicTemplates(mappingPath = "/mappings/test-dynamic_templates_mappings_three.json")
961+
private static class DynamicFieldDocument {
962+
@Nullable
963+
@Id String id;
964+
965+
@Field(name = "*_str", dynamicTemplate = true) private Map<String, String> dynamicFields = new HashMap<>();
966+
}
936967
// endregion
937968
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"dynamic_templates": [
3+
{
4+
"_str": {
5+
"match": "*_str",
6+
"mapping": {
7+
"type": "keyword"
8+
}
9+
}
10+
}
11+
]
12+
}

0 commit comments

Comments
 (0)