mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-31 17:22:11 +00:00
DynamicMapping annotation should be applicable to any object field.
Original Pull Request #1779 Closes #1767
This commit is contained in:
parent
19ec481856
commit
7ace63485d
@ -245,6 +245,7 @@ public class MappingBuilder {
|
|||||||
Field fieldAnnotation = property.findAnnotation(Field.class);
|
Field fieldAnnotation = property.findAnnotation(Field.class);
|
||||||
boolean isCompletionProperty = property.isCompletionProperty();
|
boolean isCompletionProperty = property.isCompletionProperty();
|
||||||
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);
|
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);
|
||||||
|
DynamicMapping dynamicMapping = property.findAnnotation(DynamicMapping.class);
|
||||||
|
|
||||||
if (!isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {
|
if (!isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ public class MappingBuilder {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
mapEntity(builder, persistentEntity, false, property.getFieldName(), true, fieldAnnotation.type(),
|
mapEntity(builder, persistentEntity, false, property.getFieldName(), true, fieldAnnotation.type(),
|
||||||
fieldAnnotation, property.findAnnotation(DynamicMapping.class));
|
fieldAnnotation, dynamicMapping);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,9 +275,9 @@ public class MappingBuilder {
|
|||||||
if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
|
if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
|
||||||
applyDefaultIdFieldMapping(builder, property);
|
applyDefaultIdFieldMapping(builder, property);
|
||||||
} else if (multiField != null) {
|
} else if (multiField != null) {
|
||||||
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty);
|
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty, dynamicMapping);
|
||||||
} else if (fieldAnnotation != null) {
|
} else if (fieldAnnotation != null) {
|
||||||
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty);
|
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty, dynamicMapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +378,7 @@ public class MappingBuilder {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void addSingleFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
private void addSingleFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
||||||
Field annotation, boolean nestedOrObjectField) throws IOException {
|
Field annotation, boolean nestedOrObjectField, @Nullable DynamicMapping dynamicMapping) throws IOException {
|
||||||
|
|
||||||
// build the property json, if empty skip it as this is no valid mapping
|
// build the property json, if empty skip it as this is no valid mapping
|
||||||
XContentBuilder propertyBuilder = jsonBuilder().startObject();
|
XContentBuilder propertyBuilder = jsonBuilder().startObject();
|
||||||
@ -389,6 +390,11 @@ public class MappingBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.startObject(property.getFieldName());
|
builder.startObject(property.getFieldName());
|
||||||
|
|
||||||
|
if (nestedOrObjectField && dynamicMapping != null) {
|
||||||
|
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
@ -429,10 +435,15 @@ public class MappingBuilder {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void addMultiFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
private void addMultiFieldMapping(XContentBuilder builder, ElasticsearchPersistentProperty property,
|
||||||
MultiField annotation, boolean nestedOrObjectField) throws IOException {
|
MultiField annotation, boolean nestedOrObjectField, @Nullable DynamicMapping dynamicMapping) throws IOException {
|
||||||
|
|
||||||
// main field
|
// main field
|
||||||
builder.startObject(property.getFieldName());
|
builder.startObject(property.getFieldName());
|
||||||
|
|
||||||
|
if (nestedOrObjectField && dynamicMapping != null) {
|
||||||
|
builder.field(TYPE_DYNAMIC, dynamicMapping.value().name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
|
||||||
|
|
||||||
// inner fields
|
// inner fields
|
||||||
|
@ -296,6 +296,16 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
|||||||
indexOps.delete();
|
indexOps.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #1767
|
||||||
|
@DisplayName("should write dynamic mapping entries")
|
||||||
|
void shouldWriteDynamicMappingEntries() {
|
||||||
|
|
||||||
|
IndexOperations indexOps = operations.indexOps(DynamicMappingEntity.class);
|
||||||
|
indexOps.create();
|
||||||
|
indexOps.putMapping();
|
||||||
|
indexOps.delete();
|
||||||
|
}
|
||||||
|
|
||||||
@Document(indexName = "ignore-above-index")
|
@Document(indexName = "ignore-above-index")
|
||||||
static class IgnoreAboveEntity {
|
static class IgnoreAboveEntity {
|
||||||
@Nullable @Id private String id;
|
@Nullable @Id private String id;
|
||||||
@ -1082,4 +1092,25 @@ public class MappingBuilderIntegrationTests extends MappingContextBaseTests {
|
|||||||
this.dense_vector = dense_vector;
|
this.dense_vector = dense_vector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Document(indexName = "dynamic-mapping")
|
||||||
|
@DynamicMapping(DynamicMappingValue.False)
|
||||||
|
static class DynamicMappingEntity {
|
||||||
|
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Object) private Map<String, Object> objectMap;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Author getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(Author author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||||
@ -415,23 +416,42 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test // DATAES-148, #1767
|
||||||
void shouldWriteDynamicMappingSettings() throws JSONException {
|
void shouldWriteDynamicMappingSettings() throws JSONException {
|
||||||
|
|
||||||
String expected = "{\n" + //
|
String expected = "{\n" + //
|
||||||
" \"dynamic\": \"false\",\n" + //
|
" \"dynamic\": \"false\",\n" + //
|
||||||
" \"properties\": {\n" + //
|
" \"properties\": {\n" + //
|
||||||
" \"author\": {\n" + //
|
" \"_class\": {\n" + //
|
||||||
" \"dynamic\": \"strict\",\n" + //
|
" \"type\": \"keyword\",\n" + //
|
||||||
" \"type\": \"object\",\n" + //
|
" \"index\": false,\n" + //
|
||||||
" \"properties\": {}\n" + //
|
" \"doc_values\": false\n" + //
|
||||||
|
" },\n" + //
|
||||||
|
" \"author\": {\n" + //
|
||||||
|
" \"type\": \"object\",\n" + //
|
||||||
|
" \"dynamic\": \"strict\",\n" + //
|
||||||
|
" \"properties\": {\n" + //
|
||||||
|
" \"_class\": {\n" + //
|
||||||
|
" \"type\": \"keyword\",\n" + //
|
||||||
|
" \"index\": false,\n" + //
|
||||||
|
" \"doc_values\": false\n" + //
|
||||||
|
" }\n" + //
|
||||||
" }\n" + //
|
" }\n" + //
|
||||||
|
" },\n" + //
|
||||||
|
" \"objectMap\": {\n" + //
|
||||||
|
" \"type\": \"object\",\n" + //
|
||||||
|
" \"dynamic\": \"false\"\n" + //
|
||||||
|
" },\n" + //
|
||||||
|
" \"nestedObjectMap\": {\n" + //
|
||||||
|
" \"type\": \"nested\",\n" + //
|
||||||
|
" \"dynamic\": \"false\"\n" + //
|
||||||
" }\n" + //
|
" }\n" + //
|
||||||
"}\n";
|
" }\n" + //
|
||||||
|
"}"; //
|
||||||
|
|
||||||
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
|
String mapping = getMappingBuilder().buildPropertyMapping(ConfigureDynamicMappingEntity.class);
|
||||||
|
|
||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAES-784
|
@Test // DATAES-784
|
||||||
@ -608,39 +628,38 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // #1727
|
@Test // #1727
|
||||||
@DisplayName("should map according to the annotated properties")
|
@DisplayName("should map according to the annotated properties")
|
||||||
void shouldMapAccordingToTheAnnotatedProperties() throws JSONException {
|
void shouldMapAccordingToTheAnnotatedProperties() throws JSONException {
|
||||||
|
|
||||||
String expected = "{\n" +
|
String expected = "{\n" + " \"properties\": {\n" + //
|
||||||
" \"properties\": {\n" + //
|
" \"field1\": {\n" + //
|
||||||
" \"field1\": {\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"format\": \"date_optional_time||epoch_millis\"\n" + //
|
||||||
" \"format\": \"date_optional_time||epoch_millis\"\n" + //
|
" },\n" + //
|
||||||
" },\n" + //
|
" \"field2\": {\n" + //
|
||||||
" \"field2\": {\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"format\": \"basic_date\"\n" + //
|
||||||
" \"format\": \"basic_date\"\n" + //
|
" },\n" + //
|
||||||
" },\n" + //
|
" \"field3\": {\n" + //
|
||||||
" \"field3\": {\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"format\": \"basic_date||basic_time\"\n" + //
|
||||||
" \"format\": \"basic_date||basic_time\"\n" + //
|
" },\n" + //
|
||||||
" },\n" + //
|
" \"field4\": {\n" + //
|
||||||
" \"field4\": {\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"format\": \"date_optional_time||epoch_millis||dd.MM.uuuu\"\n" + //
|
||||||
" \"format\": \"date_optional_time||epoch_millis||dd.MM.uuuu\"\n" + //
|
" },\n" + //
|
||||||
" },\n" + //
|
" \"field5\": {\n" + //
|
||||||
" \"field5\": {\n" + //
|
" \"type\": \"date\",\n" + //
|
||||||
" \"type\": \"date\",\n" + //
|
" \"format\": \"dd.MM.uuuu\"\n" + //
|
||||||
" \"format\": \"dd.MM.uuuu\"\n" + //
|
" }\n" + //
|
||||||
" }\n" + //
|
" }\n" + //
|
||||||
" }\n" + //
|
"}"; //
|
||||||
"}"; //
|
|
||||||
|
|
||||||
String mapping = getMappingBuilder().buildPropertyMapping(DateFormatsEntity.class);
|
String mapping = getMappingBuilder().buildPropertyMapping(DateFormatsEntity.class);
|
||||||
|
|
||||||
assertEquals(expected, mapping, false);
|
assertEquals(expected, mapping, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Document(indexName = "ignore-above-index")
|
@Document(indexName = "ignore-above-index")
|
||||||
static class IgnoreAboveEntity {
|
static class IgnoreAboveEntity {
|
||||||
@ -666,7 +685,6 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class FieldNameEntity {
|
static class FieldNameEntity {
|
||||||
|
|
||||||
@Document(indexName = "fieldname-index")
|
@Document(indexName = "fieldname-index")
|
||||||
@ -1199,6 +1217,10 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
static class ConfigureDynamicMappingEntity {
|
static class ConfigureDynamicMappingEntity {
|
||||||
|
|
||||||
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
@Nullable @DynamicMapping(DynamicMappingValue.Strict) @Field(type = FieldType.Object) private Author author;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Object) private Map<String, Object> objectMap;
|
||||||
|
@Nullable @DynamicMapping(DynamicMappingValue.False) @Field(
|
||||||
|
type = FieldType.Nested) private List<Map<String, Object>> nestedObjectMap;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Author getAuthor() {
|
public Author getAuthor() {
|
||||||
@ -1474,7 +1496,8 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
@Nullable @Id private String id;
|
@Nullable @Id private String id;
|
||||||
@Nullable @Field(type = FieldType.Date) private LocalDateTime field1;
|
@Nullable @Field(type = FieldType.Date) private LocalDateTime field1;
|
||||||
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDateTime field2;
|
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDateTime field2;
|
||||||
@Nullable @Field(type = FieldType.Date, format = { DateFormat.basic_date, DateFormat.basic_time }) private LocalDateTime field3;
|
@Nullable @Field(type = FieldType.Date,
|
||||||
|
format = { DateFormat.basic_date, DateFormat.basic_time }) private LocalDateTime field3;
|
||||||
@Nullable @Field(type = FieldType.Date, pattern = "dd.MM.uuuu") private LocalDateTime field4;
|
@Nullable @Field(type = FieldType.Date, pattern = "dd.MM.uuuu") private LocalDateTime field4;
|
||||||
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") private LocalDateTime field5;
|
@Nullable @Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") private LocalDateTime field5;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user