mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-25 05:22:10 +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 support for multi search template API.
|
||||
* Add support for SpEL in @Query.
|
||||
* Add support for field aliases in the index mapping.
|
||||
|
||||
[[new-features.5-2-0]]
|
||||
== New in Spring Data Elasticsearch 5.2
|
||||
|
@ -74,6 +74,13 @@ public @interface Mapping {
|
||||
*/
|
||||
String runtimeFieldsPath() default "";
|
||||
|
||||
/**
|
||||
* field alias definitions to be written to the index mapping
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
MappingAlias[] aliases() default {};
|
||||
|
||||
enum Detection {
|
||||
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)
|
||||
throws IOException {
|
||||
|
||||
if (entity != null && entity.isAnnotationPresent(Mapping.class)) {
|
||||
Mapping mappingAnnotation = entity.getRequiredAnnotation(Mapping.class);
|
||||
var mappingAnnotation = entity != null ? entity.findAnnotation(Mapping.class) : null;
|
||||
|
||||
if (mappingAnnotation != null) {
|
||||
|
||||
if (!mappingAnnotation.enabled()) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 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_TERM_VECTOR = "term_vector";
|
||||
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 boolean coerce;
|
||||
|
@ -18,10 +18,7 @@ package org.springframework.data.elasticsearch.core.index;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
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.LocalDate;
|
||||
import java.util.Collection;
|
||||
@ -269,6 +266,12 @@ public abstract class MappingBuilderIntegrationTests extends MappingContextBaseT
|
||||
operations.indexOps(SimilarityEntity.class).createWithMapping();
|
||||
}
|
||||
|
||||
@Test // #2845
|
||||
@DisplayName("should write mapping with field aliases")
|
||||
void shouldWriteMappingWithFieldAliases() {
|
||||
operations.indexOps(FieldAliasEntity.class).createWithMapping();
|
||||
}
|
||||
|
||||
// region Entities
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
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;
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
@ -19,12 +19,7 @@ package org.springframework.data.elasticsearch.core.index;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||
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.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
@ -1179,6 +1174,39 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
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
|
||||
|
||||
@Document(indexName = "ignore-above-index")
|
||||
@ -1298,8 +1326,8 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
|
||||
@Nullable
|
||||
@MultiField(mainField = @Field(name = "alternate-description", type = FieldType.Text, analyzer = "whitespace"),
|
||||
otherFields = {
|
||||
@InnerField(suffix = "suff-ix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) //
|
||||
otherFields = {
|
||||
@InnerField(suffix = "suff-ix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) //
|
||||
public String getAlternateDescription() {
|
||||
return alternateDescription;
|
||||
}
|
||||
@ -1662,7 +1690,7 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
@GeoPointField private String pointC;
|
||||
@Nullable
|
||||
@GeoPointField private double[] pointD;
|
||||
// geo shape, until e have the classes for this, us a strng
|
||||
|
||||
@Nullable
|
||||
@GeoShapeField private String shape1;
|
||||
@Nullable
|
||||
@ -2390,5 +2418,18 @@ public class MappingBuilderUnitTests extends MappingContextBaseTests {
|
||||
@Nullable
|
||||
@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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user