diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java index 38b11bf7b..be6608c68 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java @@ -32,6 +32,7 @@ import java.lang.annotation.Target; * @author Jakub Vavrik * @author Kevin Leturc * @author Peter-Josef Meisch + * @author Xiao Yu */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @@ -77,4 +78,9 @@ public @interface Field { boolean includeInParent() default false; String[] copyTo() default {}; + + /** + * @since 4.0 + */ + int ignoreAbove() default -1; } diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java index 0ca6ae425..93fc75b1a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java @@ -24,6 +24,7 @@ import java.lang.annotation.Target; * @author Artur Konczak * @author Mohsin Husen * @author Sascha Woo + * @author Xiao Yu */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @@ -48,4 +49,9 @@ public @interface InnerField { String analyzer() default ""; String normalizer() default ""; + + /** + * @since 4.0 + */ + int ignoreAbove() default -1; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java index 0eab56611..6730252a1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java @@ -48,6 +48,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste import org.springframework.data.mapping.PropertyHandler; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.JsonNode; @@ -67,6 +68,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Robert Gruendler * @author Petr Kukral * @author Peter-Josef Meisch + * @author Xiao Yu */ class MappingBuilder { @@ -85,6 +87,7 @@ class MappingBuilder { private static final String FIELD_CONTEXT_TYPE = "type"; private static final String FIELD_CONTEXT_PRECISION = "precision"; private static final String FIELD_DYNAMIC_TEMPLATES = "dynamic_templates"; + private static final String FIELD_IGNORE_ABOVE = "ignore_above"; private static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators"; private static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments"; @@ -346,6 +349,7 @@ class MappingBuilder { String searchAnalyzer = null; String normalizer = null; String[] copyTo = null; + Integer ignoreAbove = null; if (annotation instanceof Field) { // @Field @@ -360,6 +364,7 @@ class MappingBuilder { searchAnalyzer = fieldAnnotation.searchAnalyzer(); normalizer = fieldAnnotation.normalizer(); copyTo = fieldAnnotation.copyTo(); + ignoreAbove = fieldAnnotation.ignoreAbove(); } else if (annotation instanceof InnerField) { // @InnerField InnerField fieldAnnotation = (InnerField) annotation; @@ -372,6 +377,7 @@ class MappingBuilder { analyzer = fieldAnnotation.analyzer(); searchAnalyzer = fieldAnnotation.searchAnalyzer(); normalizer = fieldAnnotation.normalizer(); + ignoreAbove = fieldAnnotation.ignoreAbove(); } else { throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField"); } @@ -404,6 +410,10 @@ class MappingBuilder { if (copyTo != null && copyTo.length > 0) { builder.field(FIELD_COPY_TO, copyTo); } + if (ignoreAbove != -1) { + Assert.isTrue(ignoreAbove >= 0, "ignore_above must be a positive value"); + builder.field(FIELD_IGNORE_ABOVE, ignoreAbove); + } } /** diff --git a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java index 4a4c0dff1..d27103f24 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java @@ -80,6 +80,7 @@ import org.springframework.test.context.junit4.SpringRunner; * @author Don Wellington * @author Sascha Woo * @author Peter-Josef Meisch + * @author Xiao Yu */ @RunWith(SpringRunner.class) @ContextConfiguration("classpath:elasticsearch-template-test.xml") @@ -409,6 +410,35 @@ public class MappingBuilderTests extends MappingContextBaseTests { assertEquals(expected, mapping, false); } + @Test // DATAES-639 + public void shouldUseIgnoreAbove() throws IOException, JSONException { + + // given + String expected = "{\"ignore-above-type\":{\"properties\":{\"message\":{\"store\":false,\"type\":\"keyword\",\"ignore_above\":10}}}}"; + + // when + String mapping = getMappingBuilder().buildPropertyMapping(IgnoreAboveEntity.class); + + // then + assertEquals(expected, mapping, false); + } + + /** + * @author Xiao Yu + */ + @Setter + @Getter + @NoArgsConstructor + @AllArgsConstructor + @Builder + @Document(indexName = "ignore-above-index", type = "ignore-above-type") + static class IgnoreAboveEntity { + + @Id private String id; + + @Field(type = FieldType.Keyword, ignoreAbove = 10) private String message; + } + /** * @author Peter-Josef Meisch */