mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-26 13:52:12 +00:00
Add support for field aliases in the index mapping.
Original Pull Request #2847 Closes #2845
This commit is contained in:
parent
e9ecebd9ef
commit
0f5497338a
@ -9,6 +9,7 @@
|
|||||||
* Add shard statistics to the `SearchHit` class.
|
* Add shard statistics to the `SearchHit` class.
|
||||||
* Add support for multi search template API.
|
* Add support for multi search template API.
|
||||||
* Add support for SpEL in @Query.
|
* Add support for SpEL in @Query.
|
||||||
|
* Add support for field aliases in the index mapping.
|
||||||
|
|
||||||
[[new-features.5-2-0]]
|
[[new-features.5-2-0]]
|
||||||
== New in Spring Data Elasticsearch 5.2
|
== New in Spring Data Elasticsearch 5.2
|
||||||
|
@ -74,6 +74,13 @@ public @interface Mapping {
|
|||||||
*/
|
*/
|
||||||
String runtimeFieldsPath() default "";
|
String runtimeFieldsPath() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* field alias definitions to be written to the index mapping
|
||||||
|
*
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
MappingAlias[] aliases() default {};
|
||||||
|
|
||||||
enum Detection {
|
enum Detection {
|
||||||
DEFAULT, TRUE, FALSE;
|
DEFAULT, TRUE, FALSE;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a field alias in the index mapping.
|
||||||
|
*
|
||||||
|
* @author Peter-Josef Meisch
|
||||||
|
* @since 5.3
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface MappingAlias {
|
||||||
|
/**
|
||||||
|
* the name of the alias.
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the path of the alias.
|
||||||
|
*/
|
||||||
|
String path();
|
||||||
|
}
|
@ -214,8 +214,9 @@ public class MappingBuilder {
|
|||||||
@Nullable Field parentFieldAnnotation, @Nullable Dynamic dynamicMapping, @Nullable Document runtimeFields)
|
@Nullable Field parentFieldAnnotation, @Nullable Dynamic dynamicMapping, @Nullable Document runtimeFields)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (entity != null && entity.isAnnotationPresent(Mapping.class)) {
|
var mappingAnnotation = entity != null ? entity.findAnnotation(Mapping.class) : null;
|
||||||
Mapping mappingAnnotation = entity.getRequiredAnnotation(Mapping.class);
|
|
||||||
|
if (mappingAnnotation != null) {
|
||||||
|
|
||||||
if (!mappingAnnotation.enabled()) {
|
if (!mappingAnnotation.enabled()) {
|
||||||
objectNode.put(MAPPING_ENABLED, false);
|
objectNode.put(MAPPING_ENABLED, false);
|
||||||
@ -289,6 +290,16 @@ public class MappingBuilder {
|
|||||||
LOGGER.warn(String.format("error mapping property with name %s", property.getName()), e);
|
LOGGER.warn(String.format("error mapping property with name %s", property.getName()), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the alias entries after the properties
|
||||||
|
if (mappingAnnotation != null) {
|
||||||
|
for (MappingAlias mappingAlias : mappingAnnotation.aliases()) {
|
||||||
|
var aliasNode = propertiesNode.putObject(mappingAlias.name());
|
||||||
|
aliasNode.put(FIELD_PARAM_TYPE, FIELD_PARAM_TYPE_ALIAS);
|
||||||
|
aliasNode.put(FIELD_PARAM_PATH, mappingAlias.path());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,8 @@ public final class MappingParameters {
|
|||||||
static final String FIELD_PARAM_SIMILARITY = "similarity";
|
static final String FIELD_PARAM_SIMILARITY = "similarity";
|
||||||
static final String FIELD_PARAM_TERM_VECTOR = "term_vector";
|
static final String FIELD_PARAM_TERM_VECTOR = "term_vector";
|
||||||
static final String FIELD_PARAM_TYPE = "type";
|
static final String FIELD_PARAM_TYPE = "type";
|
||||||
|
static final String FIELD_PARAM_PATH = "path";
|
||||||
|
static final String FIELD_PARAM_TYPE_ALIAS = "alias";
|
||||||
|
|
||||||
private final String analyzer;
|
private final String analyzer;
|
||||||
private final boolean coerce;
|
private final boolean coerce;
|
||||||
|
@ -18,10 +18,7 @@ package org.springframework.data.elasticsearch.core.index;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Object;
|
|
||||||
|
|
||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -269,6 +266,12 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
|||||||
operations.indexOps(SimilarityEntity.class).createWithMapping();
|
operations.indexOps(SimilarityEntity.class).createWithMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #2845
|
||||||
|
@DisplayName("should write mapping with field aliases")
|
||||||
|
void shouldWriteMappingWithFieldAliases() {
|
||||||
|
operations.indexOps(FieldAliasEntity.class).createWithMapping();
|
||||||
|
}
|
||||||
|
|
||||||
// region Entities
|
// region Entities
|
||||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||||
static class Book {
|
static class Book {
|
||||||
@ -908,5 +911,19 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
|||||||
@Field(type = FieldType.Dense_Vector, dims = 42, similarity = "cosine") private double[] denseVector;
|
@Field(type = FieldType.Dense_Vector, dims = 42, similarity = "cosine") private double[] denseVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(aliases = {
|
||||||
|
@MappingAlias(name = "someAlly", path = "someText"),
|
||||||
|
@MappingAlias(name = "otherAlly", path = "otherText")
|
||||||
|
})
|
||||||
|
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||||
|
private static class FieldAliasEntity {
|
||||||
|
@Id
|
||||||
|
@Nullable private String id;
|
||||||
|
@Nullable
|
||||||
|
@Field(type = Text) private String someText;
|
||||||
|
@Nullable
|
||||||
|
@Field(type = Text) private String otherText;
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,7 @@ package org.springframework.data.elasticsearch.core.index;
|
|||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||||
import static org.springframework.data.elasticsearch.annotations.FieldType.Object;
|
|
||||||
|
|
||||||
import java.lang.Boolean;
|
|
||||||
import java.lang.Double;
|
|
||||||
import java.lang.Integer;
|
|
||||||
import java.lang.Object;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@ -1179,6 +1174,39 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
assertEquals(expected, mapping, true);
|
assertEquals(expected, mapping, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #2845
|
||||||
|
@DisplayName("should write field aliases to the mapping")
|
||||||
|
void shouldWriteFieldAliasesToTheMapping() throws JSONException {
|
||||||
|
|
||||||
|
var expected = """
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"_class": {
|
||||||
|
"type": "keyword",
|
||||||
|
"index": false,
|
||||||
|
"doc_values": false
|
||||||
|
},
|
||||||
|
"someText": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"otherText": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"someAlly": {
|
||||||
|
"type": "alias",
|
||||||
|
"path": "someText"
|
||||||
|
},
|
||||||
|
"otherAlly": {
|
||||||
|
"type": "alias",
|
||||||
|
"path": "otherText"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
String mapping = getMappingBuilder().buildPropertyMapping(FieldAliasEntity.class);
|
||||||
|
|
||||||
|
assertEquals(expected, mapping, true);
|
||||||
|
}
|
||||||
// region entities
|
// region entities
|
||||||
|
|
||||||
@Document(indexName = "ignore-above-index")
|
@Document(indexName = "ignore-above-index")
|
||||||
@ -1662,7 +1690,7 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
@GeoPointField private String pointC;
|
@GeoPointField private String pointC;
|
||||||
@Nullable
|
@Nullable
|
||||||
@GeoPointField private double[] pointD;
|
@GeoPointField private double[] pointD;
|
||||||
// geo shape, until e have the classes for this, us a strng
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@GeoShapeField private String shape1;
|
@GeoShapeField private String shape1;
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -2390,5 +2418,18 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Field(name = "dotted.field", type = Text) private String dottedField;
|
@Field(name = "dotted.field", type = Text) private String dottedField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(aliases = {
|
||||||
|
@MappingAlias(name = "someAlly", path = "someText"),
|
||||||
|
@MappingAlias(name = "otherAlly", path = "otherText")
|
||||||
|
})
|
||||||
|
private static class FieldAliasEntity {
|
||||||
|
@Id
|
||||||
|
@Nullable private String id;
|
||||||
|
@Nullable
|
||||||
|
@Field(type = Text) private String someText;
|
||||||
|
@Nullable
|
||||||
|
@Field(type = Text) private String otherText;
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user