Skip to content

Commit 8365812

Browse files
authored
DATAES-943 - Add missing mapping parameters.
Original PR: #534
1 parent 49068b4 commit 8365812

File tree

6 files changed

+173
-44
lines changed

6 files changed

+173
-44
lines changed

src/main/java/org/springframework/data/elasticsearch/annotations/Field.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,21 @@
168168
* @since 4.1
169169
*/
170170
boolean positiveScoreImpact() default true;
171+
172+
/**
173+
* to be used in combination with {@link FieldType#Object}
174+
*
175+
* @since 4.1
176+
*/
177+
boolean enabled() default true;
178+
179+
/**
180+
* @since 4.1
181+
*/
182+
boolean eagerGlobalOrdinals() default false;
183+
184+
/**
185+
* @since 4.1
186+
*/
187+
NullValueType nullValueType() default NullValueType.String;
171188
}

src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,14 @@
130130
* @since 4.1
131131
*/
132132
boolean positiveScoreImpact() default true;
133+
134+
/**
135+
* @since 4.1
136+
*/
137+
boolean eagerGlobalOrdinals() default false;
138+
139+
/**
140+
* @since 4.1
141+
*/
142+
NullValueType nullValueType() default NullValueType.String;
133143
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2020 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+
* @author Peter-Josef Meisch
20+
* @since 4.1
21+
*/
22+
public enum NullValueType {
23+
String, Integer, Long, Double
24+
}

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

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.data.elasticsearch.annotations.IndexOptions;
2727
import org.springframework.data.elasticsearch.annotations.IndexPrefixes;
2828
import org.springframework.data.elasticsearch.annotations.InnerField;
29+
import org.springframework.data.elasticsearch.annotations.NullValueType;
2930
import org.springframework.data.elasticsearch.annotations.Similarity;
3031
import org.springframework.data.elasticsearch.annotations.TermVector;
3132
import org.springframework.util.Assert;
@@ -44,8 +45,10 @@ public final class MappingParameters {
4445

4546
static final String FIELD_PARAM_COERCE = "coerce";
4647
static final String FIELD_PARAM_COPY_TO = "copy_to";
47-
static final String FIELD_PARAM_DOC_VALUES = "doc_values";
4848
static final String FIELD_PARAM_DATA = "fielddata";
49+
static final String FIELD_PARAM_DOC_VALUES = "doc_values";
50+
static final String FIELD_PARAM_EAGER_GLOBAL_ORDINALS = "eager_global_ordinals";
51+
static final String FIELD_PARAM_ENABLED = "enabled";
4952
static final String FIELD_PARAM_FORMAT = "format";
5053
static final String FIELD_PARAM_IGNORE_ABOVE = "ignore_above";
5154
static final String FIELD_PARAM_IGNORE_MALFORMED = "ignore_malformed";
@@ -56,44 +59,47 @@ public final class MappingParameters {
5659
static final String FIELD_PARAM_INDEX_PREFIXES_MIN_CHARS = "min_chars";
5760
static final String FIELD_PARAM_INDEX_PREFIXES_MAX_CHARS = "max_chars";
5861
static final String FIELD_PARAM_INDEX_ANALYZER = "analyzer";
62+
static final String FIELD_PARAM_MAX_SHINGLE_SIZE = "max_shingle_size";
5963
static final String FIELD_PARAM_NORMALIZER = "normalizer";
6064
static final String FIELD_PARAM_NORMS = "norms";
6165
static final String FIELD_PARAM_NULL_VALUE = "null_value";
62-
static final String FIELD_PARAMETER_NAME_POSITION_INCREMENT_GAP = "position_increment_gap";
66+
static final String FIELD_PARAM_POSITION_INCREMENT_GAP = "position_increment_gap";
67+
static final String FIELD_PARAM_POSITIVE_SCORE_IMPACT = "positive_score_impact";
6368
static final String FIELD_PARAM_SCALING_FACTOR = "scaling_factor";
6469
static final String FIELD_PARAM_SEARCH_ANALYZER = "search_analyzer";
6570
static final String FIELD_PARAM_STORE = "store";
6671
static final String FIELD_PARAM_SIMILARITY = "similarity";
6772
static final String FIELD_PARAM_TERM_VECTOR = "term_vector";
6873
static final String FIELD_PARAM_TYPE = "type";
69-
static final String FIELD_PARAM_MAX_SHINGLE_SIZE = "max_shingle_size";
70-
static final String FIELD_PARAM_POSITIVE_SCORE_IMPACT = "positive_score_impact";
7174

72-
private boolean index = true;
73-
private boolean store = false;
74-
private boolean fielddata = false;
75-
private FieldType type = null;
76-
private DateFormat dateFormat = null;
77-
private String datePattern = null;
78-
private String analyzer = null;
79-
private String searchAnalyzer = null;
80-
private String normalizer = null;
81-
private String[] copyTo = null;
82-
private Integer ignoreAbove = null;
83-
private boolean coerce = true;
84-
private boolean docValues = true;
85-
private boolean ignoreMalformed = false;
86-
private IndexOptions indexOptions = null;
87-
boolean indexPhrases = false;
88-
private IndexPrefixes indexPrefixes = null;
89-
private boolean norms = true;
90-
private String nullValue = null;
91-
private Integer positionIncrementGap = null;
92-
private Similarity similarity = Similarity.Default;
93-
private TermVector termVector = TermVector.none;
94-
private double scalingFactor = 1.0;
95-
@Nullable private Integer maxShingleSize;
96-
private boolean positiveScoreImpact = true;
75+
private final String analyzer;
76+
private final boolean coerce;
77+
@Nullable private final String[] copyTo;
78+
private final String datePattern;
79+
private final boolean docValues;
80+
private final boolean eagerGlobalOrdinals;
81+
private final boolean enabled;
82+
private final boolean fielddata;
83+
private final DateFormat format;
84+
@Nullable private final Integer ignoreAbove;
85+
private final boolean ignoreMalformed;
86+
private final boolean index;
87+
private final IndexOptions indexOptions;
88+
private final boolean indexPhrases;
89+
@Nullable private final IndexPrefixes indexPrefixes;
90+
private final String normalizer;
91+
private final boolean norms;
92+
@Nullable private final Integer maxShingleSize;
93+
private final String nullValue;
94+
private final NullValueType nullValueType;
95+
private final Integer positionIncrementGap;
96+
private final boolean positiveScoreImpact;
97+
private final String searchAnalyzer;
98+
private final double scalingFactor;
99+
private final Similarity similarity;
100+
private final boolean store;
101+
private final TermVector termVector;
102+
private final FieldType type;
97103

98104
/**
99105
* extracts the mapping parameters from the relevant annotations.
@@ -119,7 +125,7 @@ private MappingParameters(Field field) {
119125
store = field.store();
120126
fielddata = field.fielddata();
121127
type = field.type();
122-
dateFormat = field.format();
128+
format = field.format();
123129
datePattern = field.pattern();
124130
analyzer = field.analyzer();
125131
searchAnalyzer = field.searchAnalyzer();
@@ -133,11 +139,10 @@ private MappingParameters(Field field) {
133139
ignoreMalformed = field.ignoreMalformed();
134140
indexOptions = field.indexOptions();
135141
indexPhrases = field.indexPhrases();
136-
if (field.indexPrefixes().length > 0) {
137-
indexPrefixes = field.indexPrefixes()[0];
138-
}
142+
indexPrefixes = field.indexPrefixes().length > 0 ? field.indexPrefixes()[0] : null;
139143
norms = field.norms();
140144
nullValue = field.nullValue();
145+
nullValueType = field.nullValueType();
141146
positionIncrementGap = field.positionIncrementGap();
142147
similarity = field.similarity();
143148
termVector = field.termVector();
@@ -148,18 +153,22 @@ private MappingParameters(Field field) {
148153
|| (maxShingleSize >= 2 && maxShingleSize <= 4), //
149154
"maxShingleSize must be in inclusive range from 2 to 4 for field type search_as_you_type");
150155
positiveScoreImpact = field.positiveScoreImpact();
156+
Assert.isTrue(field.enabled() || type == FieldType.Object, "enabled false is only allowed for field type object");
157+
enabled = field.enabled();
158+
eagerGlobalOrdinals = field.eagerGlobalOrdinals();
151159
}
152160

153161
private MappingParameters(InnerField field) {
154162
index = field.index();
155163
store = field.store();
156164
fielddata = field.fielddata();
157165
type = field.type();
158-
dateFormat = field.format();
166+
format = field.format();
159167
datePattern = field.pattern();
160168
analyzer = field.analyzer();
161169
searchAnalyzer = field.searchAnalyzer();
162170
normalizer = field.normalizer();
171+
copyTo = null;
163172
ignoreAbove = field.ignoreAbove() >= 0 ? field.ignoreAbove() : null;
164173
coerce = field.coerce();
165174
docValues = field.docValues();
@@ -168,11 +177,10 @@ private MappingParameters(InnerField field) {
168177
ignoreMalformed = field.ignoreMalformed();
169178
indexOptions = field.indexOptions();
170179
indexPhrases = field.indexPhrases();
171-
if (field.indexPrefixes().length > 0) {
172-
indexPrefixes = field.indexPrefixes()[0];
173-
}
180+
indexPrefixes = field.indexPrefixes().length > 0 ? field.indexPrefixes()[0] : null;
174181
norms = field.norms();
175182
nullValue = field.nullValue();
183+
nullValueType = field.nullValueType();
176184
positionIncrementGap = field.positionIncrementGap();
177185
similarity = field.similarity();
178186
termVector = field.termVector();
@@ -183,6 +191,8 @@ private MappingParameters(InnerField field) {
183191
|| (maxShingleSize >= 2 && maxShingleSize <= 4), //
184192
"maxShingleSize must be in inclusive range from 2 to 4 for field type search_as_you_type");
185193
positiveScoreImpact = field.positiveScoreImpact();
194+
enabled = true;
195+
eagerGlobalOrdinals = field.eagerGlobalOrdinals();
186196
}
187197

188198
public boolean isStore() {
@@ -204,8 +214,8 @@ public void writeTypeAndParametersTo(XContentBuilder builder) throws IOException
204214

205215
if (type != FieldType.Auto) {
206216
builder.field(FIELD_PARAM_TYPE, type.name().toLowerCase());
207-
if (type == FieldType.Date && dateFormat != DateFormat.none) {
208-
builder.field(FIELD_PARAM_FORMAT, dateFormat == DateFormat.custom ? datePattern : dateFormat.toString());
217+
if (type == FieldType.Date && format != DateFormat.none) {
218+
builder.field(FIELD_PARAM_FORMAT, format == DateFormat.custom ? datePattern : format.toString());
209219
}
210220
}
211221

@@ -270,11 +280,27 @@ public void writeTypeAndParametersTo(XContentBuilder builder) throws IOException
270280
}
271281

272282
if (!StringUtils.isEmpty(nullValue)) {
273-
builder.field(FIELD_PARAM_NULL_VALUE, nullValue);
283+
Object value;
284+
switch (nullValueType) {
285+
case Integer:
286+
value = Integer.valueOf(nullValue);
287+
break;
288+
case Long:
289+
value = Long.valueOf(nullValue);
290+
break;
291+
case Double:
292+
value = Double.valueOf(nullValue);
293+
break;
294+
case String:
295+
default:
296+
value = nullValue;
297+
break;
298+
}
299+
builder.field(FIELD_PARAM_NULL_VALUE, value);
274300
}
275301

276302
if (positionIncrementGap != null && positionIncrementGap >= 0) {
277-
builder.field(FIELD_PARAMETER_NAME_POSITION_INCREMENT_GAP, positionIncrementGap);
303+
builder.field(FIELD_PARAM_POSITION_INCREMENT_GAP, positionIncrementGap);
278304
}
279305

280306
if (similarity != Similarity.Default) {
@@ -296,5 +322,13 @@ public void writeTypeAndParametersTo(XContentBuilder builder) throws IOException
296322
if (!positiveScoreImpact) {
297323
builder.field(FIELD_PARAM_POSITIVE_SCORE_IMPACT, positiveScoreImpact);
298324
}
325+
326+
if (!enabled) {
327+
builder.field(FIELD_PARAM_ENABLED, enabled);
328+
}
329+
330+
if (eagerGlobalOrdinals) {
331+
builder.field(FIELD_PARAM_EAGER_GLOBAL_ORDINALS, eagerGlobalOrdinals);
332+
}
299333
}
300334
}

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

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ public void shouldUseIgnoreAbove() throws JSONException {
305305
assertEquals(expected, mapping, false);
306306
}
307307

308-
@Test
308+
@Test // DATAES-621, DATAES-943
309309
public void shouldSetFieldMappingProperties() throws JSONException {
310310
String expected = "{\n" + //
311311
" \"properties\": {\n" + //
@@ -364,9 +364,15 @@ public void shouldSetFieldMappingProperties() throws JSONException {
364364
" \"normsFalse\": {\n" + //
365365
" \"norms\": false\n" + //
366366
" },\n" + //
367-
" \"nullValueSet\": {\n" + //
367+
" \"nullValueString\": {\n" + //
368368
" \"null_value\": \"NULLNULL\"\n" + //
369369
" },\n" + //
370+
" \"nullValueInteger\": {\n" + //
371+
" \"null_value\": 42\n" + //
372+
" },\n" + //
373+
" \"nullValueDouble\": {\n" + //
374+
" \"null_value\": 42.0\n" + //
375+
" },\n" + //
370376
" \"positionIncrementGap\": {\n" + //
371377
" \"position_increment_gap\": 42\n" + //
372378
" },\n" + //
@@ -379,6 +385,20 @@ public void shouldSetFieldMappingProperties() throws JSONException {
379385
" \"scaledFloat\": {\n" + //
380386
" \"type\": \"scaled_float\",\n" + //
381387
" \"scaling_factor\": 100.0\n" + //
388+
" },\n" + //
389+
" \"enabledObject\": {\n" + //
390+
" \"type\": \"object\"\n" + //
391+
" },\n" + //
392+
" \"disabledObject\": {\n" + //
393+
" \"type\": \"object\",\n" + //
394+
" \"enabled\": false\n" + //
395+
" },\n" + //
396+
" \"eagerGlobalOrdinalsTrue\": {\n" + //
397+
" \"type\": \"text\",\n" + //
398+
" \"eager_global_ordinals\": true\n" + //
399+
" },\n" + //
400+
" \"eagerGlobalOrdinalsFalse\": {\n" + //
401+
" \"type\": \"text\"\n" + //
382402
" }\n" + //
383403
" }\n" + //
384404
"}\n"; //
@@ -857,14 +877,20 @@ static class FieldMappingParameters {
857877
@Nullable @Field private String normsTrue;
858878
@Nullable @Field(norms = false) private String normsFalse;
859879
@Nullable @Field private String nullValueNotSet;
860-
@Nullable @Field(nullValue = "NULLNULL") private String nullValueSet;
880+
@Nullable @Field(nullValue = "NULLNULL") private String nullValueString;
881+
@Nullable @Field(nullValue = "42", nullValueType = NullValueType.Integer) private String nullValueInteger;
882+
@Nullable @Field(nullValue = "42.0", nullValueType = NullValueType.Double) private String nullValueDouble;
861883
@Nullable @Field(positionIncrementGap = 42) private String positionIncrementGap;
862884
@Nullable @Field private String similarityDefault;
863885
@Nullable @Field(similarity = Similarity.Boolean) private String similarityBoolean;
864886
@Nullable @Field private String termVectorDefault;
865887
@Nullable @Field(termVector = TermVector.with_offsets) private String termVectorWithOffsets;
866888
@Nullable @Field(type = FieldType.Scaled_Float, scalingFactor = 100.0) Double scaledFloat;
867889
@Nullable @Field(type = Auto) String autoField;
890+
@Nullable @Field(type = Object, enabled = true) private String enabledObject;
891+
@Nullable @Field(type = Object, enabled = false) private String disabledObject;
892+
@Nullable @Field(type = Text, eagerGlobalOrdinals = true) private String eagerGlobalOrdinalsTrue;
893+
@Nullable @Field(type = Text, eagerGlobalOrdinals = false) private String eagerGlobalOrdinalsFalse;
868894
}
869895

870896
@Document(indexName = "test-index-configure-dynamic-mapping")

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.springframework.data.elasticsearch.core.index;
22

33
import static org.assertj.core.api.Assertions.*;
4+
import static org.springframework.data.elasticsearch.annotations.FieldType.Object;
45

56
import java.lang.annotation.Annotation;
67

8+
import org.junit.jupiter.api.DisplayName;
79
import org.junit.jupiter.api.Test;
810
import org.springframework.data.elasticsearch.annotations.Field;
911
import org.springframework.data.elasticsearch.annotations.FieldType;
@@ -61,12 +63,28 @@ public void shouldNotAllowDocValuesFalseOnFieldTypeNested() {
6163
assertThatThrownBy(() -> MappingParameters.from(annotation)).isInstanceOf(IllegalArgumentException.class);
6264
}
6365

66+
@Test // DATAES-943
67+
@DisplayName("should allow enabled false only on object fields")
68+
void shouldAllowEnabledFalseOnlyOnObjectFields() {
69+
ElasticsearchPersistentEntity<?> failEntity = elasticsearchConverter.get().getMappingContext()
70+
.getRequiredPersistentEntity(InvalidEnabledFieldClass.class);
71+
Annotation annotation = failEntity.getRequiredPersistentProperty("disabledObject").findAnnotation(Field.class);
72+
73+
assertThatThrownBy(() -> MappingParameters.from(annotation)).isInstanceOf(IllegalArgumentException.class);
74+
}
75+
6476
static class AnnotatedClass {
6577
@Nullable @Field private String field;
6678
@Nullable @MultiField(mainField = @Field,
6779
otherFields = { @InnerField(suffix = "test", type = FieldType.Text) }) private String mainField;
6880
@Score private float score;
6981
@Nullable @Field(type = FieldType.Text, docValues = false) private String docValuesText;
7082
@Nullable @Field(type = FieldType.Nested, docValues = false) private String docValuesNested;
83+
@Nullable @Field(type = Object, enabled = true) private String enabledObject;
84+
@Nullable @Field(type = Object, enabled = false) private String disabledObject;
85+
}
86+
87+
static class InvalidEnabledFieldClass {
88+
@Nullable @Field(type = FieldType.Text, enabled = false) private String disabledObject;
7189
}
7290
}

0 commit comments

Comments
 (0)