Spring Data ElasticSearch 使用教程

1,230 阅读5分钟

版本兼容性

Spring Data Elasticsearch、Elasticsearch、Spring Framework、Spring Boot使用时需要版本兼容,否则会出现许多异常情况,下图展示的是它们各自版本的对应关系:

Spring Data Release TrainSpring Data ElasticsearchElasticsearchSpring FrameworkSpring Boot
2022.0 (Turing)5.0.x8.2.36.0.x3.0.x?
2021.2 (Raj)4.4.x7.17.35.3.x2.7.x
2021.1 (Q)4.3.x7.15.25.3.x2.6.x
2021.0 (Pascal)4.2.x[github.com/spring-proj…]7.12.05.3.x2.5.x
2020.0 (Ockham)[github.com/spring-proj…]4.1.x[github.com/spring-proj…]7.9.35.3.22.4.x
Neumann[github.com/spring-proj…]4.0.x[github.com/spring-proj…]7.6.25.2.122.3.x
Moore[github.com/spring-proj…]3.2.x[github.com/spring-proj…]6.8.125.2.122.2.x
Lovelace[github.com/spring-proj…]3.1.x[github.com/spring-proj…]6.2.25.1.192.1.x
Kay[github.com/spring-proj…]3.0.x[github.com/spring-proj…]5.5.05.0.132.0.x
Ingalls[github.com/spring-proj…]2.1.x[github.com/spring-proj…]2.4.04.3.251.5.x

官方说明地址:github.com/spring-proj…

mapping(映射)、template(模板)、alias(别名)

一、mapping

ES中的映射可以简单理解为关系型数据库中的表结构,映射的官方描述是这样的:映射是定义如何存储和索引文档及其包含的字段的过程。

举例说明,映射可以定义如下内容:

  • 应将哪些字符串字段视为全文字段
  • 哪些字段包含数字、日期或地理位置
  • 是否应将文档中所有字段的值索引到catch-all字段
  • 日期值的格式
  • 用于控制动态添加的字段映射的自定义规则

在对ES进行读写数据前,创建索引是必需的,其中创建方法有两种:

  • 推荐:使用DSL语句提前创建好映射
  • 不推荐:应用程序启动时自动创建好映射

不推荐自动创建索引,是因为有可能自动创建的索引字段类型不符合我们的预期,如果这个时候想修改字段类型以符合我们的预期,那操作起来是比较困难的,因为ES不能直接更新现有字段映射类型,只有通过“重建索引”才能更新字段映射类型,关于重建索引的详细描述,请阅读xxx

总之,映射要提前创建好。

已经创建好的映射,如何与Java的实体类对应起来,以便于我们使用Spring Data Elasticsearch来操作ES,下面举例说明:

📢 适用于ES 2.x、5.x

创建索引并指定映射

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type": "text"
        },
        "name": {
          "type": "text"
        },
        "age": {
          "type": "integer"
        },
        "create_time": {
          "type": "date",
          "format": "date_optional_time||epoch_millis"
        }
      }
    }
  }
}
  1. 创建一个名为 my_index 的索引。
  2. 创建名为 _doc 的映射类型。
  3. 指定字段或属性。
  4. 指定字段 title 类型为 text 。
  5. 指定字段 name 类型为 text 。
  6. 指定字段 age 类型为 integer 。
  7. 指定字段 create_time 包含两种可能格式的值: date_optional_time​ 或者 epoch_millis​。

Java实体类

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Document(indexName = "my_index", type = "_doc", createIndex = false)
public class MyIndexDO {
    @Id
    private String id;
    @Version
    private Long version;
    @Field(name = "title", type = FieldType.Text)
    private String title;
    @Field(name = "name", type = FieldType.Text)
    private String name;
    @Field(name = "age", type = FieldType.Integer)
    private Integer age;
    @Field(name = "create_time", type = FieldType.Date, format = DateFormat.date_optional_time)
    private Long createTime;

    // 省略get、set方法
}

@Document注解中分别指定了indexName、type、createIndex,其中有一个参数createIndex,如果此参数设置为true(这是缺省值),则在引导期间,Spring data Elasticearch将在应用程序启动时,检查是否存在由@Document注释定义的索引。如果它不存在,则将创建索引,并将从实体的注释的映射写入新创建的索引。如果此参数设置为false,则不检查不创建索引。

@Id注解用于指定文档id,这样elasticsearch文档的_id​会与我们的数据ID是一致的。

@Version注解用于指定一个属性用作版本控制,以实现对elasticsearch文档的乐观锁控制。

@Field注解可以将字段映射到Elasticsearch mapping定义。

  • name:将在Elasticsearch文档中展示的字段名,如果没有设置,则使用Java字段名。

  • type:字段类型,可以是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等等,更多字段类型请查看 Elasticsearch Mapping Types

  • format:预置的日期格式,下表展示了不同的属性和根据其值创建的映射:

    annotationformat string in Elasticsearch mapping
    @Field(type=FieldType.Date)"date_optional_time
    @Field(type=FieldType.Date, format=DateFormat.basic_date)"basic_date"
    @Field(type=FieldType.Date, format={DateFormat.basic_date, DateFormat.basic_time})"basic_date
    @Field(type=FieldType.Date, pattern="dd.MM.uuuu")"date_optional_time
    @Field(type=FieldType.Date, format={}, pattern="dd.MM.uuuu")"dd.MM.uuuu"
  • pattern:自定义日期格式

  • store:原始字段值是否应该存储在Elasticsearch中,默认值为false。

    其实不管我们将store值设置为true或false,elasticsearch都会将该字段存储到Field域中;但是他们的区别是什么?

    1. store = false时,默认设置;那么给字段只存储在"_source"的Field域中;
    2. store = true时,该字段的value会存储在一个跟_source平级的独立Field域中;同时也会存储在_source中,所以有两份拷贝。

    那么我们在什么样的业务场景下使用store field功能?

    1. _source field在索引的mapping 中disable了。这种情况下,如果不将某个field定义成store=true,那些将无法在返回的查询结果中看到这个field。
    2. _source的内容非常大。这时候如果我们想要在返回的_source document中解释出某个field的值的话,开销会很大(当然你也可以定义source filtering将减少network overhead),比例某个document中保存的是一本书,所以document中可能有这些field: title, date, content。假如我们只是想查询书的title 跟date信息,而不需要解释整个_source(非常大),这个时候我们可以考虑将title, date这些field设置成store=true。
  • analyzer,searchAnalyzer,normalizer:指定自定义分词器

📢 适用于ES 6.x、7.x、8.x

二、template

索引模板允许你定义模板,这些模板将在创建新索引时自动应用。这些模板既包括设置和映射,也包括一个简单的模式模板,控制模板是否应该应用到新索引。

模板只在索引创建时应用。改变模板不会对现有索引产生影响。当使用创建索引的API时,作为创建索引调用的一部分定义的设置将优先于模板中定义的任何匹配设置。

三、alias