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 77046fdd..cd3d9880 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Field.java @@ -161,4 +161,11 @@ public @interface Field { * @since 4.1 */ boolean storeNullValue() default false; + + /** + * to be used in combination with {@link FieldType#Rank_Feature} + * + * @since 4.1 + */ + boolean positiveScoreImpact() default true; } diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java index f2b0a3ba..5cf94e7a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/FieldType.java @@ -24,32 +24,36 @@ package org.springframework.data.elasticsearch.annotations; * @author Aleksei Arsenev */ public enum FieldType { - Auto, // - 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 // + Auto, // + 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, // + /** @since 4.1 */ + Rank_Feature, // + /** @since 4.1 */ + Rank_Features // } 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 3f6fcb28..c4cd4e7c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java @@ -123,4 +123,11 @@ public @interface InnerField { * @since 4.0 */ int maxShingleSize() default -1; + + /** + * to be used in combination with {@link FieldType#Rank_Feature} + * + * @since 4.1 + */ + boolean positiveScoreImpact() default true; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingParameters.java b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingParameters.java index d22142f1..92750c87 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingParameters.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingParameters.java @@ -67,6 +67,7 @@ public final class MappingParameters { static final String FIELD_PARAM_TERM_VECTOR = "term_vector"; static final String FIELD_PARAM_TYPE = "type"; static final String FIELD_PARAM_MAX_SHINGLE_SIZE = "max_shingle_size"; + static final String FIELD_PARAM_POSITIVE_SCORE_IMPACT = "positive_score_impact"; private boolean index = true; private boolean store = false; @@ -92,6 +93,7 @@ public final class MappingParameters { private TermVector termVector = TermVector.none; private double scalingFactor = 1.0; @Nullable private Integer maxShingleSize; + private boolean positiveScoreImpact = true; /** * extracts the mapping parameters from the relevant annotations. @@ -145,6 +147,7 @@ public final class MappingParameters { || maxShingleSize == null // || (maxShingleSize >= 2 && maxShingleSize <= 4), // "maxShingleSize must be in inclusive range from 2 to 4 for field type search_as_you_type"); + positiveScoreImpact = field.positiveScoreImpact(); } private MappingParameters(InnerField field) { @@ -179,6 +182,7 @@ public final class MappingParameters { || maxShingleSize == null // || (maxShingleSize >= 2 && maxShingleSize <= 4), // "maxShingleSize must be in inclusive range from 2 to 4 for field type search_as_you_type"); + positiveScoreImpact = field.positiveScoreImpact(); } public boolean isStore() { @@ -287,5 +291,9 @@ public final class MappingParameters { if (maxShingleSize != null) { builder.field(FIELD_PARAM_MAX_SHINGLE_SIZE, maxShingleSize); } + + if (!positiveScoreImpact) { + builder.field(FIELD_PARAM_POSITIVE_SCORE_IMPACT, positiveScoreImpact); + } } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java index 64ff01fd..13d7cdd8 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java @@ -50,6 +50,7 @@ import org.elasticsearch.search.suggest.completion.context.ContextMapping; import org.json.JSONException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Id; @@ -596,6 +597,30 @@ public class MappingBuilderTests extends MappingContextBaseTests { assertThat(propertyMapping).doesNotContain("seqNoPrimaryTerm"); } + @Test // DATAES-854 + @DisplayName("should write rank_feature properties") + void shouldWriteRankFeatureProperties() throws JSONException { + String expected = "{\n" + // + " \"properties\": {\n" + // + " \"pageRank\": {\n" + // + " \"type\": \"rank_feature\"\n" + // + " },\n" + // + " \"urlLength\": {\n" + // + " \"type\": \"rank_feature\",\n" + // + " \"positive_score_impact\": false\n" + // + " },\n" + // + " \"topics\": {\n" + // + " \"type\": \"rank_features\"\n" + // + " }\n" + // + " }\n" + // + "}\n"; // + + String mapping = getMappingBuilder().buildPropertyMapping(RankFeatureEntity.class); + + System.out.println(mapping); + assertEquals(expected, mapping, false); + } + /** * @author Xiao Yu */ @@ -1072,4 +1097,15 @@ public class MappingBuilderTests extends MappingContextBaseTests { @Field(type = Object) private SeqNoPrimaryTerm seqNoPrimaryTerm; } + + @Data + static class RankFeatureEntity { + @Id private String id; + + @Field(type = FieldType.Rank_Feature) private Integer pageRank; + + @Field(type = FieldType.Rank_Feature, positiveScoreImpact = false) private Integer urlLength; + + @Field(type = FieldType.Rank_Features) private Map topics; + } }