Skip to content

Commit c0fa91c

Browse files
committed
Refresh entities mapping cache.
Signed-off-by: Youssef Aouichaoui <[email protected]>
1 parent 88f2ed3 commit c0fa91c

8 files changed

+191
-10
lines changed

src/main/java/org/springframework/data/elasticsearch/client/elc/IndicesTemplate.java

+42
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.data.elasticsearch.core.IndexInformation;
3535
import org.springframework.data.elasticsearch.core.IndexOperations;
3636
import org.springframework.data.elasticsearch.core.ResourceUtil;
37+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
3738
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
3839
import org.springframework.data.elasticsearch.core.document.Document;
3940
import org.springframework.data.elasticsearch.core.index.*;
@@ -145,6 +146,8 @@ protected boolean doCreate(IndexCoordinates indexCoordinates, Map<String, Object
145146

146147
CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexSettings);
147148
CreateIndexResponse createIndexResponse = execute(client -> client.create(createIndexRequest));
149+
// refresh cached mappings
150+
refreshEntitiesMapping();
148151
return Boolean.TRUE.equals(createIndexResponse.acknowledged());
149152
}
150153

@@ -241,6 +244,45 @@ public Map<String, Object> getMapping() {
241244
return responseConverter.indicesGetMapping(getMappingResponse, indexCoordinates);
242245
}
243246

247+
@Override
248+
public ClusterMapping getClusterMapping() {
249+
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(IndexCoordinates.of("*"));
250+
GetMappingResponse getMappingResponse = execute(client -> client.getMapping(getMappingRequest));
251+
252+
return responseConverter.indicesGetMapping(getMappingResponse);
253+
}
254+
255+
/**
256+
* Refreshes the mapping of entities.
257+
* <p>
258+
* This method is responsible for retrieving and updating the metadata related to the entities.
259+
*/
260+
private void refreshEntitiesMapping() {
261+
ClusterMapping clusterMapping = getClusterMapping();
262+
for (ClusterMapping.ClusterMappingEntry mappingEntry : clusterMapping) {
263+
// Get entity
264+
Class<?> entity = null;
265+
for (ElasticsearchPersistentEntity<?> persistentEntity : this.elasticsearchConverter.getMappingContext().getPersistentEntities()) {
266+
if (mappingEntry.getName().equals(persistentEntity.getIndexCoordinates().getIndexName())) {
267+
entity = persistentEntity.getType();
268+
269+
break;
270+
}
271+
}
272+
273+
if (entity == null) {
274+
continue;
275+
}
276+
277+
if (mappingEntry.getMappings().containsKey("dynamic_templates")) {
278+
Object dynamicTemplates = mappingEntry.getMappings().get("dynamic_templates");
279+
if (dynamicTemplates instanceof List<?> value) {
280+
getRequiredPersistentEntity(entity).buildDynamicTemplates(value);
281+
}
282+
}
283+
}
284+
}
285+
244286
@Override
245287
public Settings createSettings() {
246288
return createSettings(checkForBoundClass());

src/main/java/org/springframework/data/elasticsearch/client/elc/ReactiveIndicesTemplate.java

+9
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.data.elasticsearch.core.IndexInformation;
3737
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
3838
import org.springframework.data.elasticsearch.core.ReactiveResourceUtil;
39+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
3940
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
4041
import org.springframework.data.elasticsearch.core.document.Document;
4142
import org.springframework.data.elasticsearch.core.index.*;
@@ -218,6 +219,14 @@ public Mono<Document> getMapping() {
218219
return getMappingResponse.map(response -> responseConverter.indicesGetMapping(response, indexCoordinates));
219220
}
220221

222+
@Override
223+
public Mono<ClusterMapping> getClusterMapping() {
224+
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(IndexCoordinates.of("*"));
225+
Mono<GetMappingResponse> getMappingResponse = Mono.from(execute(client -> client.getMapping(getMappingRequest)));
226+
227+
return getMappingResponse.map(responseConverter::indicesGetMapping);
228+
}
229+
221230
@Override
222231
public Mono<Settings> createSettings() {
223232
return createSettings(checkForBoundClass());

src/main/java/org/springframework/data/elasticsearch/client/elc/ResponseConverter.java

+11
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.springframework.data.elasticsearch.core.IndexInformation;
5353
import org.springframework.data.elasticsearch.core.MultiGetItem;
5454
import org.springframework.data.elasticsearch.core.cluster.ClusterHealth;
55+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
5556
import org.springframework.data.elasticsearch.core.document.Document;
5657
import org.springframework.data.elasticsearch.core.index.AliasData;
5758
import org.springframework.data.elasticsearch.core.index.Settings;
@@ -213,6 +214,16 @@ public Document indicesGetMapping(GetMappingResponse getMappingResponse, IndexCo
213214
return Document.parse(toJson(indexMappingRecord.mappings(), jsonpMapper));
214215
}
215216

217+
public ClusterMapping indicesGetMapping(GetMappingResponse getMappingResponse) {
218+
ClusterMapping.Builder builder = ClusterMapping.builder();
219+
for (String indexName : getMappingResponse.result().keySet()) {
220+
Map<String, Object> mappings = indicesGetMapping(getMappingResponse, IndexCoordinates.of(indexName));
221+
builder.withMapping(ClusterMapping.ClusterMappingEntry.builder(indexName).withMappings(mappings).build());
222+
}
223+
224+
return builder.build();
225+
}
226+
216227
public List<IndexInformation> indicesGetIndexInformations(GetIndexResponse getIndexResponse) {
217228

218229
Assert.notNull(getIndexResponse, "getIndexResponse must not be null");

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

+1-10
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.Collections;
2121
import java.util.Iterator;
2222
import java.util.List;
23-
import java.util.Map;
2423
import java.util.Objects;
2524
import java.util.concurrent.CompletableFuture;
2625
import java.util.stream.Collectors;
@@ -103,6 +102,7 @@ public AbstractElasticsearchTemplate(@Nullable ElasticsearchConverter elasticsea
103102
// initialize the VersionInfo class in the initialization phase
104103
// noinspection ResultOfMethodCallIgnored
105104
VersionInfo.versionProperties();
105+
// TODO: cache entities metadata
106106
}
107107

108108
/**
@@ -603,15 +603,6 @@ protected <T> SearchDocumentResponse.EntityCreator<T> getEntityCreator(ReadDocum
603603
// region Entity callbacks
604604
protected <T> T maybeCallbackBeforeConvert(T entity, IndexCoordinates index) {
605605

606-
// get entity metadata
607-
Map<String, Object> mapping = indexOps(index).getMapping();
608-
if (mapping.containsKey("dynamic_templates")) {
609-
Object dynamicTemplates = mapping.get("dynamic_templates");
610-
if (dynamicTemplates instanceof List<?> value) {
611-
getRequiredPersistentEntity(entity.getClass()).buildDynamicTemplates(value);
612-
}
613-
}
614-
615606
if (entityCallbacks != null) {
616607
return entityCallbacks.callback(BeforeConvertCallback.class, entity, index);
617608
}

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

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Map;
2020
import java.util.Set;
2121

22+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
2223
import org.springframework.data.elasticsearch.core.document.Document;
2324
import org.springframework.data.elasticsearch.core.index.*;
2425
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
@@ -144,6 +145,13 @@ default boolean putMapping(Class<?> clazz) {
144145
*/
145146
Map<String, Object> getMapping();
146147

148+
/**
149+
* Get mappings of all indices in a cluster.
150+
*
151+
* @return Retrieve the mappings for all indices within a cluster.
152+
*/
153+
ClusterMapping getClusterMapping();
154+
147155
// endregion
148156

149157
// region settings

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

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core;
1717

18+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
1819
import reactor.core.publisher.Mono;
1920

2021
import java.util.List;
@@ -96,6 +97,11 @@ public Map<String, Object> getMapping() {
9697
return Objects.requireNonNull(reactiveIndexOperations.getMapping().block());
9798
}
9899

100+
@Override
101+
public ClusterMapping getClusterMapping() {
102+
return Objects.requireNonNull(reactiveIndexOperations.getClusterMapping().block());
103+
}
104+
99105
@Override
100106
public Settings createSettings() {
101107
return Objects.requireNonNull(reactiveIndexOperations.createSettings().block());

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

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core;
1717

18+
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
1819
import reactor.core.publisher.Flux;
1920
import reactor.core.publisher.Mono;
2021

@@ -144,6 +145,13 @@ default Mono<Boolean> putMapping(Class<?> clazz) {
144145
* @return the mapping
145146
*/
146147
Mono<Document> getMapping();
148+
149+
/**
150+
* Get mappings of all indices in a cluster.
151+
*
152+
* @return Retrieve the mappings for all indices within a cluster.
153+
*/
154+
Mono<ClusterMapping> getClusterMapping();
147155
// endregion
148156

149157
// region settings
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.elasticsearch.core.cluster;
17+
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.HashMap;
21+
import java.util.Iterator;
22+
import java.util.List;
23+
import java.util.Map;
24+
25+
import org.jetbrains.annotations.NotNull;
26+
27+
/**
28+
* Retrieves mapping definitions of all indices in the cluster.
29+
*
30+
* @author Youssef Aouichaoui
31+
* @since 5.4
32+
*/
33+
public class ClusterMapping implements Iterable<ClusterMapping.ClusterMappingEntry> {
34+
private final List<ClusterMappingEntry> mappings;
35+
36+
private ClusterMapping(Builder builder) {
37+
this.mappings = builder.mappings;
38+
}
39+
40+
@NotNull
41+
@Override
42+
public Iterator<ClusterMappingEntry> iterator() {
43+
return mappings.iterator();
44+
}
45+
46+
public static Builder builder() {
47+
return new Builder();
48+
}
49+
50+
public static class ClusterMappingEntry {
51+
private final String name;
52+
private final Map<String, Object> mappings;
53+
54+
private ClusterMappingEntry(Builder builder) {
55+
this.name = builder.name;
56+
this.mappings = builder.mappings;
57+
}
58+
59+
public String getName() {
60+
return name;
61+
}
62+
63+
public Map<String, Object> getMappings() {
64+
return Collections.unmodifiableMap(mappings);
65+
}
66+
67+
public static Builder builder(String name) {
68+
return new Builder(name);
69+
}
70+
71+
public static class Builder {
72+
private final String name;
73+
private final Map<String, Object> mappings = new HashMap<>();
74+
75+
private Builder(String name) {
76+
this.name = name;
77+
}
78+
79+
public Builder withMappings(Map<String, Object> mappings) {
80+
this.mappings.putAll(mappings);
81+
82+
return this;
83+
}
84+
85+
public ClusterMappingEntry build() {
86+
return new ClusterMappingEntry(this);
87+
}
88+
}
89+
}
90+
91+
public static class Builder {
92+
private final List<ClusterMappingEntry> mappings = new ArrayList<>();
93+
94+
private Builder() {}
95+
96+
public Builder withMapping(ClusterMappingEntry entry) {
97+
mappings.add(entry);
98+
99+
return this;
100+
}
101+
102+
public ClusterMapping build() {
103+
return new ClusterMapping(this);
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)