Skip to content

Commit ce3a615

Browse files
committed
Support custom classes for dynamic templates.
Signed-off-by: Youssef Aouichaoui <[email protected]>
1 parent 9226ab7 commit ce3a615

File tree

3 files changed

+74
-18
lines changed

3 files changed

+74
-18
lines changed

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

+20-8
Original file line numberDiff line numberDiff line change
@@ -677,13 +677,18 @@ private <R> void populateFieldsUsingDynamicTemplates(ElasticsearchPersistentEnti
677677
ElasticsearchPersistentProperty property = targetEntity
678678
.getPersistentPropertyWithFieldName(templateEntry.getKey());
679679
if (property != null && property.isDynamicFieldMapping()) {
680-
targetEntity.getPropertyAccessor(result).setProperty(property,
681-
document.entrySet().stream()
682-
.filter(fieldKey -> templateEntry.getValue().getMatch().stream()
683-
.anyMatch(regex -> simpleMatch(regex, fieldKey.getKey()))
684-
&& templateEntry.getValue().getUnmatch().stream()
685-
.noneMatch(regex -> simpleMatch(regex, fieldKey.getKey())))
686-
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
680+
// prepare value
681+
Map<String, Object> values = new HashMap<>();
682+
// TODO: Path match and unmatched
683+
document.entrySet().stream()
684+
.filter(fieldKey -> templateEntry.getValue().getMatch().stream()
685+
.anyMatch(regex -> simpleMatch(regex, fieldKey.getKey()))
686+
&& templateEntry.getValue().getUnmatch().stream()
687+
.noneMatch(regex -> simpleMatch(regex, fieldKey.getKey())))
688+
.forEach(entry -> values.put(entry.getKey(), entry.getValue()));
689+
690+
// set property
691+
targetEntity.getPropertyAccessor(result).setProperty(property, read(property.getType(), Document.from(values)));
687692
}
688693
}
689694
}
@@ -1089,7 +1094,14 @@ protected void writeProperty(ElasticsearchPersistentProperty property, Object va
10891094

10901095
addCustomTypeKeyIfNecessary(value, document, TypeInformation.of(property.getRawType()));
10911096
writeInternal(value, document, entity);
1092-
sink.set(property, document);
1097+
if (property.isDynamicFieldMapping()) {
1098+
// flatten
1099+
for (Entry<String, Object> entry : document.entrySet()) {
1100+
sink.set(entry.getKey(), entry.getValue());
1101+
}
1102+
} else {
1103+
sink.set(property, document);
1104+
}
10931105
}
10941106

10951107
/**

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

+45-10
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,7 @@
2323

2424
import java.time.Instant;
2525
import java.time.LocalDate;
26-
import java.util.Collection;
27-
import java.util.Collections;
28-
import java.util.Date;
29-
import java.util.HashMap;
30-
import java.util.HashSet;
31-
import java.util.List;
32-
import java.util.Map;
33-
import java.util.Set;
26+
import java.util.*;
3427

3528
import org.junit.jupiter.api.BeforeEach;
3629
import org.junit.jupiter.api.DisplayName;
@@ -293,15 +286,24 @@ void shouldMapDynamicFields() {
293286

294287
DynamicFieldDocument document = new DynamicFieldDocument();
295288
document.dynamicFields = Map.of("a_str", randomUUID().toString(), "b_str", randomUUID().toString());
289+
document.value = new DynamicFieldDocument.Value(1L, new Date());
296290
operations.save(document);
297291

298292
// When
299-
SearchHits<DynamicFieldDocument> results = operations.search(new StringQuery(MATCH_ALL), DynamicFieldDocument.class);
293+
SearchHits<DynamicFieldDocument> results = operations.search(new StringQuery(MATCH_ALL),
294+
DynamicFieldDocument.class);
300295

301296
// Then
302297
assertThat(results.getTotalHits()).isEqualTo(1);
303-
assertThat(results.getSearchHits()).first().extracting(SearchHit::getContent).extracting(doc -> doc.dynamicFields)
298+
assertThat(results.getSearchHits()).first()
299+
.extracting(SearchHit::getContent)
300+
.extracting(doc -> doc.dynamicFields)
304301
.isEqualTo(document.dynamicFields);
302+
assertThat(results.getSearchHits()).first()
303+
.extracting(SearchHit::getContent)
304+
.extracting(doc -> doc.value)
305+
.isEqualTo(document.value);
306+
305307
documentOperations.delete();
306308
}
307309

@@ -966,6 +968,39 @@ private static class DynamicFieldDocument {
966968
@Id String id;
967969

968970
@Field(name = "_str", dynamicTemplate = true) private Map<String, String> dynamicFields = new HashMap<>();
971+
972+
@Nullable
973+
@Field(name = "obj", dynamicTemplate = true) private Value value;
974+
975+
static class Value {
976+
@Nullable
977+
@Field(name = "value_sum", type = FieldType.Long)
978+
private Long sum;
979+
980+
@Nullable
981+
@Field(name = "value_date", type = FieldType.Long)
982+
private Date date;
983+
984+
public Value() {
985+
}
986+
987+
public Value(Long sum, Date date) {
988+
this.sum = sum;
989+
this.date = date;
990+
}
991+
992+
@Override
993+
public boolean equals(Object o) {
994+
if (this == o) return true;
995+
if (!(o instanceof Value value)) return false;
996+
return Objects.equals(sum, value.sum) && Objects.equals(date, value.date);
997+
}
998+
999+
@Override
1000+
public int hashCode() {
1001+
return Objects.hash(sum, date);
1002+
}
1003+
}
9691004
}
9701005
// endregion
9711006
}

Diff for: src/test/resources/mappings/test-dynamic_templates_mappings_three.json

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
"type": "keyword"
88
}
99
}
10+
},
11+
{
12+
"obj": {
13+
"match": "value_*",
14+
"mapping": {
15+
"type": "text",
16+
"index": false
17+
}
18+
}
1019
}
1120
]
1221
}

0 commit comments

Comments
 (0)