Skip to content

Commit 8bc133d

Browse files
authored
DATAES-148 - Dynamic mapping setting.
Original PR: #344
1 parent 26ab706 commit 8bc133d

File tree

4 files changed

+115
-12
lines changed

4 files changed

+115
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2019 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.annotations;
17+
18+
import java.lang.annotation.Documented;
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
/**
25+
* Annotation to set the dynamic mapping mode
26+
* {@see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic.html">elasticsearch doc</a>}
27+
*
28+
* @author Peter-Josef Meisch
29+
* @since 4.0
30+
*/
31+
@Retention(RetentionPolicy.RUNTIME)
32+
@Target({ ElementType.TYPE, ElementType.FIELD })
33+
@Documented
34+
public @interface DynamicMapping {
35+
36+
DynamicMappingValue value() default DynamicMappingValue.True;
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2019 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.annotations;
17+
18+
/**
19+
* values for the {@link DynamicMapping annotation}
20+
*
21+
* @author Peter-Josef Meisch
22+
* @since 4.0
23+
*/
24+
public enum DynamicMappingValue {
25+
True, False, Strict
26+
}

src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java

+16-12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.data.annotation.Transient;
3434
import org.springframework.data.elasticsearch.annotations.CompletionContext;
3535
import org.springframework.data.elasticsearch.annotations.CompletionField;
36+
import org.springframework.data.elasticsearch.annotations.DynamicMapping;
3637
import org.springframework.data.elasticsearch.annotations.DynamicTemplates;
3738
import org.springframework.data.elasticsearch.annotations.Field;
3839
import org.springframework.data.elasticsearch.annotations.FieldType;
@@ -86,6 +87,7 @@ public class MappingBuilder {
8687
private static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
8788
private static final String COMPLETION_CONTEXTS = "contexts";
8889

90+
private static final String TYPE_DYNAMIC = "dynamic";
8991
private static final String TYPE_VALUE_KEYWORD = "keyword";
9092
private static final String TYPE_VALUE_GEO_POINT = "geo_point";
9193
private static final String TYPE_VALUE_COMPLETION = "completion";
@@ -120,13 +122,9 @@ public String buildPropertyMapping(Class<?> clazz) throws IOException {
120122
builder.startObject(FIELD_PARENT).field(FIELD_PARAM_TYPE, parentType).endObject();
121123
}
122124

123-
// Properties
124-
builder.startObject(FIELD_PROPERTIES);
125-
126-
mapEntity(builder, entity, true, "", false, FieldType.Auto, null);
125+
mapEntity(builder, entity, true, "", false, FieldType.Auto, null, entity.findAnnotation(DynamicMapping.class));
127126

128-
builder.endObject() // FIELD_PROPERTIES
129-
.endObject() // indexType
127+
builder.endObject() // indexType
130128
.endObject() // root object
131129
.close();
132130

@@ -135,7 +133,7 @@ public String buildPropertyMapping(Class<?> clazz) throws IOException {
135133

136134
private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject,
137135
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType,
138-
@Nullable Field parentFieldAnnotation) throws IOException {
136+
@Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping) throws IOException {
139137

140138
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
141139
if (writeNestedProperties) {
@@ -146,14 +144,17 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten
146144

147145
if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null
148146
&& parentFieldAnnotation.includeInParent()) {
149-
150147
builder.field("include_in_parent", parentFieldAnnotation.includeInParent());
151148
}
149+
}
152150

153-
builder.startObject(FIELD_PROPERTIES);
151+
if (dynamicMapping != null) {
152+
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
154153
}
155-
if (entity != null) {
156154

155+
builder.startObject(FIELD_PROPERTIES);
156+
157+
if (entity != null) {
157158
entity.doWithProperties((PropertyHandler<ElasticsearchPersistentProperty>) property -> {
158159
try {
159160
if (property.isAnnotationPresent(Transient.class) || isInIgnoreFields(property, parentFieldAnnotation)) {
@@ -167,9 +168,12 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten
167168
});
168169
}
169170

171+
builder.endObject();
172+
170173
if (writeNestedProperties) {
171-
builder.endObject().endObject();
174+
builder.endObject();
172175
}
176+
173177
}
174178

175179
private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject,
@@ -205,7 +209,7 @@ private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject,
205209
: null;
206210

207211
mapEntity(builder, persistentEntity, false, property.getFieldName(), isNestedOrObjectProperty,
208-
fieldAnnotation.type(), fieldAnnotation);
212+
fieldAnnotation.type(), fieldAnnotation, property.findAnnotation(DynamicMapping.class));
209213

210214
if (isNestedOrObjectProperty) {
211215
return;

src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java

+36
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,27 @@ public void shouldSetFieldMappingProperties() throws JSONException, IOException
514514
assertEquals(expected, mapping, true);
515515
}
516516

517+
@Test
518+
void shouldWriteDynamicMappingSettings() throws IOException, JSONException {
519+
520+
String expected = "{\n" + //
521+
" \"dms\": {\n" + //
522+
" \"dynamic\": \"false\",\n" + //
523+
" \"properties\": {\n" + //
524+
" \"author\": {\n" + //
525+
" \"dynamic\": \"strict\",\n" + //
526+
" \"type\": \"object\",\n" + //
527+
" \"properties\": {}\n" + //
528+
" }\n" + //
529+
" }\n" + //
530+
" }\n" + //
531+
"}\n";
532+
533+
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
534+
535+
assertEquals(expected, mapping, true);
536+
}
537+
517538
/**
518539
* @author Xiao Yu
519540
*/
@@ -948,4 +969,19 @@ static class FieldMappingParameters {
948969
@Field(termVector = TermVector.with_offsets) private String termVectorWithOffsets;
949970
@Field(type = FieldType.Scaled_Float, scalingFactor = 100.0) Double scaledFloat;
950971
}
972+
973+
@Document(indexName = "test-index-configure-dynamic-mapping", type = "dms")
974+
@DynamicMapping(DynamicMappingValue.False)
975+
static class ConfigureDynamicMappingEntity {
976+
977+
@DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
978+
979+
public Author getAuthor() {
980+
return author;
981+
}
982+
983+
public void setAuthor(Author author) {
984+
this.author = author;
985+
}
986+
}
951987
}

0 commit comments

Comments
 (0)