Spring Data Elasticsearch
1.新增功能
1.1 Spring Data Elasticsearch 4.1新功能
-
使用Spring 5.3。
-
升级到Elasticsearch 7.9.3。
-
改进的别名管理API。
-
介绍ReactiveIndexOperations用于索引管理。
-
索引模板支持。
-
使用GeoJson支持地理形状数据。
1.2Spring Data Elasticsearch 4.0的新功能
-
使用Spring 5.2。
-
升级到Elasticsearch 7.6.2。
-
弃用TransportClient用法。
-
实现大多数可用于索引映射的映射类型。
-
移除Jackson ObjectMapper,现在使用
MappingElasticsearchConverter
-
清除*Operations接口中的API,对方法进行分组和重命名,以使其与Elasticsearch API匹配,弃用旧方法,并与其他Spring Data模块保持一致。
-
引入SearchHit类以表示找到的文档以及该文档的相关结果元数据(即sortValues)。
-
引入SearchHits类以表示整个搜索结果以及完整搜索结果的元数据(即max_score)。
-
引入SearchPage类以表示包含SearchHits实例的分页结果。
-
GeoDistanceOrder能够根据地理距离进行分类的课程介绍
2.项目元数据
-
版本控制-https://github.com/spring-projects/spring-data-elasticsearch
-
API文档- https: //docs.spring.io/spring-data/elasticsearch/docs/current/api/
-
Bugtracker- https: //jira.spring.io/browse/DATAES
-
发布存储库- https: //repo.spring.io/libs-release
-
里程碑资料库- https: //repo.spring.io/libs-milestone
-
快照存储库- https: //repo.spring.io/libs-snapshot
3. 使用要求
3.1版本号对应springboot的版本
4.使用Spring Data Repository
Spring数据存储库抽象的目标是显着减少实现各种持久性存储的数据访问层所需的样板代码量。
4.1 核心概念
Spring Data存储库抽象中的中央接口是Repository。它需要域类
以及域类的ID类型
作为类型参数来进行管理。该接口主要用作标记接口,以捕获要使用的类型并帮助您发现扩展该接口的接口。该CrudRepository
接口为正在管理的实体类提供复杂的CRUD功能。
例子1. CrudRepository接口
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity); 1
Optional<T> findById(ID primaryKey); 2
Iterable<T> findAll(); 3
long count(); 4
void delete(T entity); 5
boolean existsById(ID primaryKey); 6
// … more functionality omitted.
}
- 保存给定的实体。
- 返回由给定ID标识的实体。
- 返回所有实体。
- 返回实体数。
- 删除给定的实体。
- 指示是否存在具有给定ID的实体
在之上CrudRepository,有一个PagingAndSortingRepository
抽象,它添加了其他方法来简化对实体
的分页访问
:
例子2. PagingAndSortingRepository
org.springframework.data.domain.Pageable
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
5.Elasticsearch客户端
从TransportClientElasticsearch 7开始不推荐使用
例子5.1.运输客户
@Configuration
public class TransportClientConfig extends ElasticsearchConfigurationSupport {
@Bean
public Client elasticsearchClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
return client;
}
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(elasticsearchClient());
}
}
// ...
IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
.source(someObject)
.setRefreshPolicy(IMMEDIATE);
IndexResponse response = client.index(request);
- 在TransportClient必须与群集名称进行配置。
- 连接客户端的主机和端口。
5.2 高机REST客户端
Java高级REST客户端
是Elasticsearch的默认客户端
TransportClient它接受和返回完全相同的请求/响应对象,因此可以直接替换,
例子5.2.高级REST客户端
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
// ...
@Autowired
RestHighLevelClient highLevelClient;
RestClient lowLevelClient = highLevelClient.lowLevelClient();
// ...
IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
.source(singletonMap("feature", "high-level-rest-client"))
.setRefreshPolicy(IMMEDIATE);
IndexResponse response = highLevelClient.index(request);
- 使用构建器来提供集群地址,设置默认值HttpHeaders或启用SSL。
- 创建RestHighLevelClient。
- 也有可能获得lowLevelRest()客户。
6. Elasticsearch对象映射
Spring Data Elasticsearch Object Mapping是将Java对象(域实体)映射到存储在Elasticsearch中的JSON表示形式并反向映射的过程。
Spring Data Elasticsearch的早期版本使用基于Jackson的转换,Spring Data Elasticsearch 3.2.x
引入了元模型对象映射。从4.0版开始,仅使用元对象映射
,不再MappingElasticsearchConverter使用基于Jackson的映射器,而是使用。
删除基于Jackson的映射器的主要原因是:
需要使用诸如@JsonFormat或的批注来完成字段的自定义映射@JsonInclude。当同一对象用于不同的基于JSON的数据存储中或通过基于JSON的API发送时,这通常会引起问题。
自定义字段类型和格式也需要存储到Elasticsearch索引映射中。基于Jackson的注释未完全提供表示Elasticsearch类型所需的所有信息。
不仅在从实体到实体的转换时,还必须在查询参数,返回的数据以及其他地方映射字段。
MappingElasticsearchConverter现在使用涵盖所有这些情况。
6.1 映射注释概述
在MappingElasticsearchConverter使用元数据驱动的对象的映射文件。元数据取自可以注释的实体属性。
提供以下注释:
@Document:在类级别应用,以指示该类是映射到数据库的候选对象。最重要的属性是:
indexName:用于存储此实体的索引的名称。它可以包含SpEL模板表达式,例如 "log-#{T(java.time.LocalDate).now().toString()}"
type:映射类型。如果未设置,则使用小写的类的简单名称。(从版本4.0开始不推荐使用)
shards:索引的分片数。
replicas:索引的副本数。
refreshIntervall:索引的刷新间隔。用于索引创建。默认值为“ 1s”。
indexStoreType:索引的索引存储类型。用于索引创建。默认值为“ fs”。
createIndex:标记是否在存储库引导中创建索引。默认值为true。请参见使用相应的映射自动创建索引
versionType:版本管理的配置。默认值为EXTERNAL。
@Id:在字段级别应用,以标记用于标识目的的字段。
@Transient:默认情况下,存储或检索文档时,所有字段都映射到文档,此注释不包括该字段。
@PersistenceConstructor:标记从数据库实例化对象时要使用的给定构造函数,甚至是受保护的程序包。构造函数自变量按名称映射到检索到的Document中的键值。
@Field:在字段级别应用并定义字段的属性,大多数属性映射到各自的Elasticsearch映射定义(以下列表不完整,请查看注释Javadoc以获得完整参考):
name:字段名称,因为它将在Elasticsearch文档中表示,如果未设置,则使用Java字段名称。
type:字段类型,可以是文本,关键字,长整数,短整数,字节,双精度,浮点型,半浮点数,标度浮点数,日期,日期_纳米,布尔值,二进制,整数,整数范围,浮点数范围,长范围,双精度范围,日期范围,对象,嵌套,Ip,TokenCount,过滤器,展平,Search_As_You_Type。请参阅Elasticsearch映射类型
format和日期类型的pattern定义。
store:标记原始字段值是否应存储在Elasticsearch中,默认值为false。
analyzer,searchAnalyzer,normalizer用于指定自定义分析和正规化。
@GeoPoint:将字段标记为geo_point数据类型。如果字段是GeoPoint类的实例,则可以省略。
从TemporalAccessor类型派生或属于类型的属性java.util.Date必须具有类型的@Field注释FieldType.Date和DateFormat.none与之不同的格式,或者必须为此类型注册自定义转换器。
如果您使用的是自定义日期格式,则需要使用uuuu作为年份而不是yyyy。这是由于Elasticsearch 7中的更改。
6.2. 映射规则
例子:.类型提示
public class Person {
@Id String id;
String firstname;
String lastname;
}
{
"_class" : "com.example.Person",
"id" : "cb7bef",
"firstname" : "Sarah",
"lastname" : "Connor"
}
可以将类型提示配置为保存自定义信息。使用@TypeAlias注释来做到这一点。
@TypeAlias("human")
public class Person {
@Id String id;
// ...
}
{
"_class" : "human",
"id" : ...
}
8.Elasticsearch存储库
例子73.样本Book实体
@Document(indexName="books")
class Book {
@Id
private String id;
@Field(type = FieldType.text)
private String name;
@Field(type = FieldType.text)
private String summary;
@Field(type = FieldType.Integer)
private Integer price;
// getter/setter ...
}
8.1 查询创建
interface BookRepository extends Repository<Book, String> {
List<Book> findByNameAndPrice(String name, Integer price);
}
{
"query": {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}
}