Skip to content

Commit ebac4c0

Browse files
committed
Polishing.
1 parent 31b488d commit ebac4c0

File tree

3 files changed

+101
-12
lines changed

3 files changed

+101
-12
lines changed

Diff for: src/main/asciidoc/reference/elasticsearch-object-mapping.adoc

+45-8
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,58 @@ Constructor arguments are mapped by name to the key values in the retrieved Docu
5858
** `name`: The name of the field as it will be represented in the Elasticsearch document, if not set, the Java field name is used.
5959
** `type`: The field type, can be one of _Text, Keyword, Long, Integer, Short, Byte, Double, Float, Half_Float, Scaled_Float, Date, Date_Nanos, Boolean, Binary, Integer_Range, Float_Range, Long_Range, Double_Range, Date_Range, Ip_Range, Object, Nested, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type_.
6060
See https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html[Elasticsearch Mapping Types]
61-
** `format`: One or more built-in formats, default value is _strict_date_optional_time_ and _epoch_millis_.
62-
See https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats[Elasticsearch Built In Formats]
63-
** `pattern`: One or more custom date formats. NOTE: If you want to use only custom date formats, you must set the `format` property to empty `{}`.
64-
See https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#custom-date-formats[Elasticsearch Custom Date Formats]
61+
** `format`: One or more built-in date formats, see the next section <<elasticsearch.mapping.meta-model.date-formats>>.
62+
** `pattern`: One or more custom date formats, see the next section <<elasticsearch.mapping.meta-model.date-formats>>.
6563
** `store`: Flag whether the original field value should be store in Elasticsearch, default value is _false_.
6664
** `analyzer`, `searchAnalyzer`, `normalizer` for specifying custom analyzers and normalizer.
6765
* `@GeoPoint`: Marks a field as _geo_point_ datatype.
6866
Can be omitted if the field is an instance of the `GeoPoint` class.
6967

70-
NOTE: Properties that derive from `TemporalAccessor` or are of type `java.util.Date` must either have a `@Field` annotation of type `FieldType.Date`.
71-
If you are using a custom date format, you need to use _uuuu_ for the year instead of _yyyy_.
72-
This is due to a https://www.elastic.co/guide/en/elasticsearch/reference/current/migrate-to-java-time.html#java-time-migration-incompatible-date-formats[change in Elasticsearch 7].
73-
7468
The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic.
7569

70+
[[elasticsearch.mapping.meta-model.date-formats]]
71+
==== Date format mapping
72+
73+
Properties that derive from `TemporalAccessor` or are of type `java.util.Date` must either have a `@Field` annotation
74+
of type `FieldType.Date` or a custom converter must be registered for this type. This paragraph describes the use of
75+
`FieldType.Date`.
76+
77+
There are two attributes of the `@Field` annotation that define which date format information is written to the
78+
mapping (also see https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats[Elasticsearch Built In Formats] and https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#custom-date-formats[Elasticsearch Custom Date Formats])
79+
80+
The `format` attributes is used to define at least one of the predefined formats. If it is not defined, then a
81+
default value of __date_optional_time_ and _epoch_millis_ is used.
82+
83+
The `pattern` attribute can be used to add additional custom format strings. If you want to use only custom date formats, you must set the `format` property to empty `{}`.
84+
85+
The following table shows the different attributes and the mapping created from their values:
86+
87+
88+
[cols=2*,options=header]
89+
|===
90+
| annotation
91+
| format string in Elasticsearch mapping
92+
93+
| @Field(type=FieldType.Date)
94+
| "date_optional_time\|\|epoch_millis",
95+
96+
| @Field(type=FieldType.Date, format=DateFormat.basic_date)
97+
| "basic_date"
98+
99+
| @Field(type=FieldType.Date, format={DateFormat.basic_date, DateFormat.basic_time})
100+
| "basic_date\|\|basic_time"
101+
102+
| @Field(type=FieldType.Date, pattern="dd.MM.uuuu")
103+
| "date_optional_time\|\|epoch_millis\|\|dd.MM.uuuu",
104+
105+
| @Field(type=FieldType.Date, format={}, pattern="dd.MM.uuuu")
106+
| "dd.MM.uuuu"
107+
108+
|===
109+
110+
NOTE: If you are using a custom date format, you need to use _uuuu_ for the year instead of _yyyy_.
111+
This is due to a https://www.elastic.co/guide/en/elasticsearch/reference/current/migrate-to-java-time.html#java-time-migration-incompatible-date-formats[change in Elasticsearch 7].
112+
76113
==== Mapped field names
77114

78115
Without further configuration, Spring Data Elasticsearch will use the property name of an object as field name in Elasticsearch. This can be changed for individual field by using the `@Field` annotation on that property.

Diff for: src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.data.elasticsearch.annotations.MultiField;
3232
import org.springframework.data.elasticsearch.annotations.Parent;
3333
import org.springframework.data.elasticsearch.core.completion.Completion;
34+
import org.springframework.data.elasticsearch.core.convert.ConversionException;
3435
import org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter;
3536
import org.springframework.data.elasticsearch.core.geo.GeoJson;
3637
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
@@ -191,8 +192,7 @@ private void initDateConverter() {
191192
// register converters for custom formats
192193
for (String dateFormatPattern : dateFormatPatterns) {
193194
if (!StringUtils.hasText(dateFormatPattern)) {
194-
throw new MappingException(
195-
String.format("Date pattern of property '%s' must not be empty", property));
195+
throw new MappingException(String.format("Date pattern of property '%s' must not be empty", property));
196196
}
197197
converters.add(ElasticsearchDateConverter.of(dateFormatPattern));
198198
}
@@ -216,7 +216,7 @@ public Object read(String s) {
216216
}
217217
}
218218

219-
throw new RuntimeException(String
219+
throw new ConversionException(String
220220
.format("Unable to parse date value '%s' of property '%s' with configured converters", s, property));
221221
}
222222

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

+53-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.lang.Object;
3535
import java.math.BigDecimal;
3636
import java.time.LocalDate;
37+
import java.time.LocalDateTime;
3738
import java.util.Collection;
3839
import java.util.Date;
3940
import java.util.HashMap;
@@ -614,6 +615,40 @@ void shouldWriteTypeHintEntries() throws JSONException {
614615
assertEquals(expected, mapping, false);
615616
}
616617

618+
@Test // #1727
619+
@DisplayName("should map according to the annotated properties")
620+
void shouldMapAccordingToTheAnnotatedProperties() throws JSONException {
621+
622+
String expected = "{\n" +
623+
" \"properties\": {\n" + //
624+
" \"field1\": {\n" + //
625+
" \"type\": \"date\",\n" + //
626+
" \"format\": \"date_optional_time||epoch_millis\"\n" + //
627+
" },\n" + //
628+
" \"field2\": {\n" + //
629+
" \"type\": \"date\",\n" + //
630+
" \"format\": \"basic_date\"\n" + //
631+
" },\n" + //
632+
" \"field3\": {\n" + //
633+
" \"type\": \"date\",\n" + //
634+
" \"format\": \"basic_date||basic_time\"\n" + //
635+
" },\n" + //
636+
" \"field4\": {\n" + //
637+
" \"type\": \"date\",\n" + //
638+
" \"format\": \"date_optional_time||epoch_millis||dd.MM.uuuu\"\n" + //
639+
" },\n" + //
640+
" \"field5\": {\n" + //
641+
" \"type\": \"date\",\n" + //
642+
" \"format\": \"dd.MM.uuuu\"\n" + //
643+
" }\n" + //
644+
" }\n" + //
645+
"}"; //
646+
647+
String mapping = getMappingBuilder().buildPropertyMapping(DateFormatsEntity.class);
648+
649+
assertEquals(expected, mapping, false);
650+
}
651+
617652
@Setter
618653
@Getter
619654
@NoArgsConstructor
@@ -971,7 +1006,7 @@ public void setAuthor(Author author) {
9711006
}
9721007

9731008
static class ValueObject {
974-
private String value;
1009+
private final String value;
9751010

9761011
public ValueObject(String value) {
9771012
this.value = value;
@@ -1060,4 +1095,21 @@ static class ObjectEntity {
10601095
@Field(type = Text) private String objectField;
10611096
}
10621097
}
1098+
1099+
@Data
1100+
@AllArgsConstructor
1101+
@NoArgsConstructor
1102+
static class DateFormatsEntity {
1103+
@Id private String id;
1104+
@Field(type = FieldType.Date) private LocalDateTime field1;
1105+
1106+
@Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDateTime field2;
1107+
1108+
@Field(type = FieldType.Date,
1109+
format = { DateFormat.basic_date, DateFormat.basic_time }) private LocalDateTime field3;
1110+
1111+
@Field(type = FieldType.Date, pattern = "dd.MM.uuuu") private LocalDateTime field4;
1112+
1113+
@Field(type = FieldType.Date, format = {}, pattern = "dd.MM.uuuu") private LocalDateTime field5;
1114+
}
10631115
}

0 commit comments

Comments
 (0)