mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-22 20:12:11 +00:00
parent
26ab706e87
commit
8bc133d955
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation to set the dynamic mapping mode
|
||||||
|
* {@see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic.html">elasticsearch doc</a>}
|
||||||
|
*
|
||||||
|
* @author Peter-Josef Meisch
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.FIELD })
|
||||||
|
@Documented
|
||||||
|
public @interface DynamicMapping {
|
||||||
|
|
||||||
|
DynamicMappingValue value() default DynamicMappingValue.True;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch.annotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* values for the {@link DynamicMapping annotation}
|
||||||
|
*
|
||||||
|
* @author Peter-Josef Meisch
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public enum DynamicMappingValue {
|
||||||
|
True, False, Strict
|
||||||
|
}
|
@ -33,6 +33,7 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
import org.springframework.data.annotation.Transient;
|
import org.springframework.data.annotation.Transient;
|
||||||
import org.springframework.data.elasticsearch.annotations.CompletionContext;
|
import org.springframework.data.elasticsearch.annotations.CompletionContext;
|
||||||
import org.springframework.data.elasticsearch.annotations.CompletionField;
|
import org.springframework.data.elasticsearch.annotations.CompletionField;
|
||||||
|
import org.springframework.data.elasticsearch.annotations.DynamicMapping;
|
||||||
import org.springframework.data.elasticsearch.annotations.DynamicTemplates;
|
import org.springframework.data.elasticsearch.annotations.DynamicTemplates;
|
||||||
import org.springframework.data.elasticsearch.annotations.Field;
|
import org.springframework.data.elasticsearch.annotations.Field;
|
||||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||||
@ -86,6 +87,7 @@ public class MappingBuilder {
|
|||||||
private static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
|
private static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
|
||||||
private static final String COMPLETION_CONTEXTS = "contexts";
|
private static final String COMPLETION_CONTEXTS = "contexts";
|
||||||
|
|
||||||
|
private static final String TYPE_DYNAMIC = "dynamic";
|
||||||
private static final String TYPE_VALUE_KEYWORD = "keyword";
|
private static final String TYPE_VALUE_KEYWORD = "keyword";
|
||||||
private static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
private static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
||||||
private static final String TYPE_VALUE_COMPLETION = "completion";
|
private static final String TYPE_VALUE_COMPLETION = "completion";
|
||||||
@ -120,13 +122,9 @@ public class MappingBuilder {
|
|||||||
builder.startObject(FIELD_PARENT).field(FIELD_PARAM_TYPE, parentType).endObject();
|
builder.startObject(FIELD_PARENT).field(FIELD_PARAM_TYPE, parentType).endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties
|
mapEntity(builder, entity, true, "", false, FieldType.Auto, null, entity.findAnnotation(DynamicMapping.class));
|
||||||
builder.startObject(FIELD_PROPERTIES);
|
|
||||||
|
|
||||||
mapEntity(builder, entity, true, "", false, FieldType.Auto, null);
|
builder.endObject() // indexType
|
||||||
|
|
||||||
builder.endObject() // FIELD_PROPERTIES
|
|
||||||
.endObject() // indexType
|
|
||||||
.endObject() // root object
|
.endObject() // root object
|
||||||
.close();
|
.close();
|
||||||
|
|
||||||
@ -135,7 +133,7 @@ public class MappingBuilder {
|
|||||||
|
|
||||||
private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject,
|
private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject,
|
||||||
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType,
|
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType,
|
||||||
@Nullable Field parentFieldAnnotation) throws IOException {
|
@Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping) throws IOException {
|
||||||
|
|
||||||
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
|
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
|
||||||
if (writeNestedProperties) {
|
if (writeNestedProperties) {
|
||||||
@ -146,14 +144,17 @@ public class MappingBuilder {
|
|||||||
|
|
||||||
if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null
|
if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null
|
||||||
&& parentFieldAnnotation.includeInParent()) {
|
&& parentFieldAnnotation.includeInParent()) {
|
||||||
|
|
||||||
builder.field("include_in_parent", parentFieldAnnotation.includeInParent());
|
builder.field("include_in_parent", parentFieldAnnotation.includeInParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.startObject(FIELD_PROPERTIES);
|
|
||||||
}
|
}
|
||||||
if (entity != null) {
|
|
||||||
|
|
||||||
|
if (dynamicMapping != null) {
|
||||||
|
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.startObject(FIELD_PROPERTIES);
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
entity.doWithProperties((PropertyHandler<ElasticsearchPersistentProperty>) property -> {
|
entity.doWithProperties((PropertyHandler<ElasticsearchPersistentProperty>) property -> {
|
||||||
try {
|
try {
|
||||||
if (property.isAnnotationPresent(Transient.class) || isInIgnoreFields(property, parentFieldAnnotation)) {
|
if (property.isAnnotationPresent(Transient.class) || isInIgnoreFields(property, parentFieldAnnotation)) {
|
||||||
@ -167,9 +168,12 @@ public class MappingBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.endObject();
|
||||||
|
|
||||||
if (writeNestedProperties) {
|
if (writeNestedProperties) {
|
||||||
builder.endObject().endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject,
|
private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject,
|
||||||
@ -205,7 +209,7 @@ public class MappingBuilder {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
mapEntity(builder, persistentEntity, false, property.getFieldName(), isNestedOrObjectProperty,
|
mapEntity(builder, persistentEntity, false, property.getFieldName(), isNestedOrObjectProperty,
|
||||||
fieldAnnotation.type(), fieldAnnotation);
|
fieldAnnotation.type(), fieldAnnotation, property.findAnnotation(DynamicMapping.class));
|
||||||
|
|
||||||
if (isNestedOrObjectProperty) {
|
if (isNestedOrObjectProperty) {
|
||||||
return;
|
return;
|
||||||
|
@ -514,6 +514,27 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
|||||||
assertEquals(expected, mapping, true);
|
assertEquals(expected, mapping, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldWriteDynamicMappingSettings() throws IOException, JSONException {
|
||||||
|
|
||||||
|
String expected = "{\n" + //
|
||||||
|
" \"dms\": {\n" + //
|
||||||
|
" \"dynamic\": \"false\",\n" + //
|
||||||
|
" \"properties\": {\n" + //
|
||||||
|
" \"author\": {\n" + //
|
||||||
|
" \"dynamic\": \"strict\",\n" + //
|
||||||
|
" \"type\": \"object\",\n" + //
|
||||||
|
" \"properties\": {}\n" + //
|
||||||
|
" }\n" + //
|
||||||
|
" }\n" + //
|
||||||
|
" }\n" + //
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
|
||||||
|
|
||||||
|
assertEquals(expected, mapping, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Xiao Yu
|
* @author Xiao Yu
|
||||||
*/
|
*/
|
||||||
@ -948,4 +969,19 @@ public class MappingBuilderTests extends MappingContextBaseTests {
|
|||||||
@Field(termVector = TermVector.with_offsets) private String termVectorWithOffsets;
|
@Field(termVector = TermVector.with_offsets) private String termVectorWithOffsets;
|
||||||
@Field(type = FieldType.Scaled_Float, scalingFactor = 100.0) Double scaledFloat;
|
@Field(type = FieldType.Scaled_Float, scalingFactor = 100.0) Double scaledFloat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Document(indexName = "test-index-configure-dynamic-mapping", type = "dms")
|
||||||
|
@DynamicMapping(DynamicMappingValue.False)
|
||||||
|
static class ConfigureDynamicMappingEntity {
|
||||||
|
|
||||||
|
@DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
||||||
|
|
||||||
|
public Author getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(Author author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user