Elasticsearch 对象映射
Spring Data Elasticsearch 对象映射是将 Java 对象——域实体——映射到存储在 Elasticsearch 中的 JSON 表示并返回的过程。内部用于这种映射的类是映射Elasticsearch转换器.
元模型对象映射
基于元模型的方法使用域类型信息来读取/写入 Elasticsearch。这使得注册成为可能转炉特定领域类型映射的实例。
映射注释概述
这映射Elasticsearch转换器使用元数据驱动对象映射到文档。元数据取自实体属性,可以进行注释。
以下注释可用:
-
@Document: 在类级应用,表示该类是映射到数据库的候选对象。最重要的属性是(完整属性列表请参阅API文档):-
索引名称:存储该实体的索引名称。这可以包含像这样的SpEL模板表达式“log-#{T(java.time.LocalDate).now().toString()}” -
createIndex: 标记是否在仓库引导时创建索引。默认值为true。参见自动创建索引及其对应映射
-
-
@Id:在场层级应用,用于标记用于身份目的的场域。 -
@Transient,@ReadOnlyProperty,@WriteOnlyProperty详情请参见下节“控制哪些属性被写入并从Elasticsearch读取”。 -
@PersistenceConstructor: 标记给定的构造子——即使是包保护的构造子——以便在从数据库实例化对象时使用。构造函数参数通过名称映射到检索到文档中的键值。 -
@Field:在场层级应用并定义字段属性时,大多数属性对应到相应的Elasticsearch Mapping定义(以下列表不完整,详见Javadoc注释以获取完整参考):-
名称: 字段名称,如 Elasticsearch 文档中表示,若未设置,则使用 Java 字段名称。 -
类型字段类型可以是文本、关键词、长、整数、短、字节、双倍、浮点、Half_Float、Scaled_Float、日期、Date_Nanos、布尔、二进制、Integer_Range、Float_Range、Long_Range、Double_Range、Date_Range、Ip_Range、对象、嵌套、ip、Tokens计数、渗滤器、扁平化、Search_As_You_Type。参见弹性搜索映射类型。如果字段类型未指定,默认为场类型.自动. 这意味着该属性不会写入映射条目,Elasticsearch会在存储该属性的第一个数据时动态添加映射条目(请查看Elasticsearch文档中的动态映射规则)。 -
格式:一个或多个内置日期格式,详见下一节“日期格式映射”。 -
模式: 一个或多个自定义日期格式,见下一节“日期格式映射”。 -
商店: 标记原始字段值是否应存储在Elasticsearch中,默认值为false。 -
分析器,搜索分析仪,归一化用于指定定制分析仪和归一化器。
-
-
@GeoPoint:将字段标记为geo_point数据类型。如果字段是地理点类。 -
@ValueConverter定义了一个用于转换给定属性的类。与注册的Spring的区别转炉这只转换注释属性,而非所有类型属性。
映射元数据基础设施在一个独立的 Spring-Data-Commons 项目中定义,该项目与技术无关。
控制哪些属性写入和读取 Elasticsearch
本节详细说明了定义属性值是写入还是读取Elasticsearch的注释。
@Transient:带有该注释的属性不会写入映射,其值不会发送到Elasticsearch,且当文档从Elasticsearch返回时,该属性不会在生成的实体中被设置。
@ReadOnlyProperty:带有该注释的属性不会被写入 Elasticsearch,但返回数据时,该属性会被填入文档中从 Elasticsearch 返回的值。
其中一个用例是索引映射中定义的运行时字段。
@WriteOnlyProperty: 带有该注释的属性会存储在 Elasticsearch 中,但在读取文档时不会被设置为任何值。
例如,这可用于合成字段,这些字段本应放在Elasticsearch索引中,但其他地方未使用。
日期格式映射
由时间辅助器或为类型java.util.Date必须有@Field类型的注释字段类型。日期或者必须为这种类型注册定制转换器。
本段描述了字段类型。日期.
有两个属性@Field定义将哪些日期格式信息写入映射的注释(另见 Elasticsearch 内置格式和 Elasticsearch 自定义日期格式)
这格式属性用于定义至少一个预定义格式。
如果未定义,则默认值为_date_optional_time和epoch_millis。
这模式属性可用于添加额外的自定义格式字符串。
如果你只想使用自定义日期格式,必须设置格式属性为空。{}
下表展示了不同的属性及其值生成的映射:
| 注解 | Elasticsearch 映射中的格式字符串 |
|---|---|
@Field(type=FieldType.Date) |
“date_optional_time||epoch_millis“, |
@Field(type=FieldType.Date, format=DateFormat.basic_date) |
“basic_date” |
@Field(type=FieldType.Date, format={DateFormat.basic_date, DateFormat.basic_time}) |
“basic_date||basic_time” |
@Field(type=FieldType.Date, pattern=“dd.MM.uuuu”) |
“date_optional_time||epoch_millis||dd.MM.uuuu“, |
@Field(type=FieldType.Date, format={}, pattern=“dd.MM.uuuu”) |
“dd.MM。呜呜呜” |
| 如果你用的是自定义日期格式,年份需要用uuuu代替yyyy。 这是由于Elasticsearch 7的变更。 |
请查阅org.springframework.data.elasticsearch.annotations.DateFormatenum,表示预定义值及其模式的完整列表。
射击场类型
当字段被注释为Integer_Range、Float_Range、Long_Range、Double_Range、Date_Range 或Ip_Range中的类型时,该字段必须是将映射到弹性搜索范围的类的实例,例如:
class SomePersonData {
@Field(type = FieldType.Integer_Range)
private ValidAge validAge;
// getter and setter
}
class ValidAge {
@Field(name="gte")
private Integer from;
@Field(name="lte")
private Integer to;
// getter and setter
}
作为替代方案,Spring Data Elasticsearch 提供了射程<T>类,使得前一个例子可以写成:
class SomePersonData {
@Field(type = FieldType.Integer_Range)
private Range<Integer> validAge;
// getter and setter
}
该类型的支持类别<了>是整数,长,浮,双,日期以及实现时间辅助器接口。
映射字段名称
无需进一步配置,Spring Data Elasticsearch 将使用对象的属性名称作为 Elasticsearch 中的字段名。
可以通过使用@Field对该属性的注释。
也可以定义场命名策略在客户端配置(Elasticsearch 客户端)中。
例如,如果SnakeCaseField命名策略在配置中,对象的 sampleProperty 会映射到 Elasticsearch 中的 sample_property。
一个场命名策略适用于所有实体;可以通过设置特定名称 来覆盖@Field在一处房产上。
非场支持性质
通常,实体中使用的属性是实体类的场。
有时,物业价值在实体中计算,应存储在Elasticsearch中。
在这种情况下,getter方法(getProperty())可以用@Field注释,此外,方法还必须注释为@AccessType(AccessType.Type
.财产).
在这种情况下,需要的第三个注释是@WriteOnlyProperty,因此该值只写入 Elasticsearch。
完整示例:
@Field(type = Keyword)
@WriteOnlyProperty
@AccessType(AccessType.Type.PROPERTY)
public String getProperty() {
return "some value that is calculated here";
}
映射规则
类型提示
映射使用嵌入文档中的类型提示,以实现通用类型映射。
这些类型提示表示为_类文档中的属性为每个聚合根编写。
public class Person { (1)
@Id String id;
String firstname;
String lastname;
}
{
"_class" : "com.example.Person", (1)
"id" : "cb7bef",
"firstname" : "Sarah",
"lastname" : "Connor"
}
| 1 | 默认情况下,类型提示使用域名类型的类名。 |
类型提示可以配置为存储自定义信息。
使用该@TypeAlias注释以实现这一点。
确保添加类型@TypeAlias到初始实体集(AbstractElasticsearchConfiguration#getInitialEntitySet)在首次读取存储数据时,已经拥有实体信息。 |
@TypeAlias("human") (1)
public class Person {
@Id String id;
// ...
}
{
"_class" : "human", (1)
"id" : ...
}
| 1 | 配置的别名用于编写实体。 |
除非属性类型为对象,接口或实际值类型与属性声明不匹配。 |
禁用类型提示
当应使用的索引已经存在且映射中未定义类型提示且映射模式设置为严格时,可能需要禁用类型提示的写入。 在这种情况下,写入类型提示会产生错误,因为该字段无法自动添加。
通过覆盖该方法,可以在整个应用中禁用类型提示writeTypeHints()在由摘要Elasticsearch配置(参见 Elasticsearch 客户端)
作为替代方案,对于单个索引,可以禁用@Document注解:
@Document(indexName = "index", writeTypeHint = WriteTypeHint.FALSE)
| 我们强烈建议不要禁用类型提示。 只有在被迫的情况下才这么做。 禁用类型提示可能导致文档在多态性数据中无法正确检索,或者文档检索完全失败。 |
地理空间类型
地理空间类型如点 & 地理点转换为纬度/经度对。
public class Address {
String city, street;
Point location;
}
{
"city" : "Los Angeles",
"street" : "2800 East Observatory Road",
"location" : { "lat" : 34.118347, "lon" : -118.3026284 }
}
GeoJson 类型
Spring Data Elasticsearch 通过提供接口支持 GeoJson 类型GeoJson以及不同几何形状的实现。
它们根据 GeoJson 规范映射到 Elasticsearch 文档。
实体的对应属性在索引映射中指定为geo_shape当索引映射被写入时。(也请查看Elasticsearch文档)
public class Address {
String city, street;
GeoJsonPoint location;
}
{
"city": "Los Angeles",
"street": "2800 East Observatory Road",
"location": {
"type": "Point",
"coordinates": [-118.3026284, 34.118347]
}
}
以下 GeoJson 类型被实现:
-
GeoJsonPoint -
GeoJsonMultiPoint -
GeoJsonLineString -
GeoJsonMultiLineString -
GeoJsonPolygon -
GeoJsonMultiPolygon -
GeoJsonGeometryCollection
收集
对于集合中的值,在类型提示和自定义转换方面,应用与聚合根相同的映射规则。
public class Person {
// ...
List<Person> friends;
}
{
// ...
"friends" : [ { "firstname" : "Kyle", "lastname" : "Reese" } ]
}
地图
对于 Maps 内部的值,在类型提示和自定义转换方面,应用与聚合根相同的映射规则。 然而,Map键需要被Elasticsearch处理一个字符串。
public class Person {
// ...
Map<String, Address> knownLocations;
}
{
// ...
"knownLocations" : {
"arrivedAt" : {
"city" : "Los Angeles",
"street" : "2800 East Observatory Road",
"location" : { "lat" : 34.118347, "lon" : -118.3026284 }
}
}
}
自定义转换
正在看配置摘自上一节 Elasticsearch自定义转换允许注册特定映射域和简单类型的规则。
@Configuration
public class Config extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder() //
.connectedTo("localhost:9200") //
.build();
}
@Bean
@Override
public ElasticsearchCustomConversions elasticsearchCustomConversions() {
return new ElasticsearchCustomConversions(
Arrays.asList(new AddressToMap(), new MapToAddress())); (1)
}
@WritingConverter (2)
static class AddressToMap implements Converter<Address, Map<String, Object>> {
@Override
public Map<String, Object> convert(Address source) {
LinkedHashMap<String, Object> target = new LinkedHashMap<>();
target.put("ciudad", source.getCity());
// ...
return target;
}
}
@ReadingConverter (3)
static class MapToAddress implements Converter<Map<String, Object>, Address> {
@Override
public Address convert(Map<String, Object> source) {
// ...
return address;
}
}
}
{
"ciudad" : "Los Angeles",
"calle" : "2800 East Observatory Road",
"localidad" : { "lat" : 34.118347, "lon" : -118.3026284 }
}
| 1 | 加转炉实现。 |
| 2 | 设置转炉用于书写域类型转至Elasticsearch。 |
| 3 | 设置转炉用于阅读域类型来自搜索结果。 |