Elasticsearch 4. Spring Boot整合Elasticsearch

Spring Boot整合elasticsearch

目前常用的Spring Boot整合elasticsearch的java客户端有:

spring-boot-starter-data-elasticsearch、spring-data-elasticsearch,由Spring提供的elasticsearch的封装,上手简单(类似JPA的操作),缺点是更新慢,SpringBoot 2.2.x才提供对es7.x的支持。

Java High Level REST Client由官方推出,其代码语法和DSL语法(前文讲的ES操作语法)很相似,前文学了高级操作语法后用此java客户端就是熟悉api和用法的问题,和DSL语法一样用法较灵活。

下面是这两种客户端与Spring Boot的简单整合(es版本为7.2)。

一、spring-boot-starter-data-elasticsearch

​ 为支持es7.x版本,整合用的spring boot版本升级到了2.2.0

1 依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2 yml配置文件
spring:
    elasticsearch:
       rest:
         uris: http://192.168.75.128:9200
         username: elastic
         password: 123456
3 编辑实体类(对象映射)

参考官网:https://docs.spring.io/spring-data/elasticsearch/docs/4.2.1/reference/html/#elasticsearch.mapping

几种重要的摘出来:

  • @Document: 应用于类级别,表示该类是映射到数据库的候选。最重要的属性是:

    • indexName:存储该实体的索引名称。这可以包含一个 SpEL 模板表达式,如 “log-#{T(java.time.LocalDate).now().toString()}”
  • @Id:在字段级别应用以标记用于标识目的的字段。

  • @Field:应用于字段级别,定义字段的属性,大部分属性映射到各自的Elasticsearch Mapping定义(以下列表不完整,完整参考Javadoc注解):

    • 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之一, 嵌套, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type

例子:

@Document(indexName = "shop", type = "_doc")
public class Shop {
	@Id
	private String id;
	@Field(type = FieldType.Keyword)
	private String name;
	@Field(type = FieldType.Keyword)
	private String price;
}
4 编辑持久层操作类

参考官网:https://docs.spring.io/spring-data/elasticsearch/docs/4.2.1/reference/html/#elasticsearch.repositories

类似于JPA的操作,根据实体类创建Repository接口进行操作。

例子:

public interface ShopRepository extends ElasticsearchRepository<Shop, String> {
}

Repository封装好的方法有:在这里插入图片描述

也可以自定义方法以及使用ElasticsearchRestTemplate来操作。

5 根据方法名称自动实现自定义方法

不过需要遵从一定的约定:方法命名和参数

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
OrfindByNameOrPrice{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
IsfindByName{"bool" : {"must" : {"field" : {"name" : "?"}}}}
NotfindByNameNot{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
BetweenfindByPriceBetween{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqualfindByPriceLessThan{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqualfindByPriceGreaterThan{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
BeforefindByPriceBefore{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
AfterfindByPriceAfter{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
LikefindByNameLike{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWithfindByNameStartingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWithfindByNameEndingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/ContainingfindByNameContaining{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
InfindByNameIn(Collection<String>names){"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotInfindByNameNotIn(Collection<String>names){"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
NearfindByStoreNearNot Supported Yet !
TruefindByAvailableTrue{"bool" : {"must" : {"field" : {"available" : true}}}}
FalsefindByAvailableFalse{"bool" : {"must" : {"field" : {"available" : false}}}}
OrderByfindByAvailableTrueOrderByNameDesc{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
6 高级查询

若想实现复杂的查询或统计,就要通过QueryBuilders实现高级查询,详查API,基本用法如下:

// 基本查询
TermQueryBuilder termQuery = QueryBuilders.termQuery(name, value);
shopRepository.search(termQuery);// 执行查询
// 另外还有其它基本查询
QueryBuilders.matchQuery(name, text);
QueryBuilders.rangeQuery("").lt(to);
// ...

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 多条件查询
queryBuilder.withQuery(QueryBuilders.termQuery("name", "ww"));
queryBuilder.withQuery(QueryBuilders.rangeQuery("").gt(""));
// 设置分页参数
queryBuilder.withPageable(PageRequest.of(0, 10));
// 排序
queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
// 执行查询
shopRepository.search(queryBuilder.build());

// 聚合,类型为terms,聚合名称为names,聚合字段为name
queryBuilder.addAggregation(
AggregationBuilders.terms("names").field("name"));
// 执行查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Shop> aggPage = (AggregatedPage<Shop>) this.shopRepository.search(queryBuilder.build());

// 组合查询
BoolQueryBuilder baseQueryBuild = QueryBuilders.boolQuery();
// 查询 price=12 and (name = ls or name = zs)
BoolQueryBuilder shouldQueryBuild = QueryBuilders.boolQuery();
shouldQueryBuild.should(QueryBuilders.termQuery("name", "ls"));
shouldQueryBuild.should(QueryBuilders.termQuery("name", "zs"));
baseQueryBuild.filter(QueryBuilders.termQuery("price", "12"));
baseQueryBuild.filter(shouldQueryBuild);
// 执行查询
this.shopRepository.search(baseQueryBuild);

二、Java High Level REST Client

1 依赖
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.2.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.2.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.2.0</version>
</dependency>
2 yml配置文件
elasticsearch:
    uris: http://192.168.75.128:9200
    username: elastic
    password: 123456
3 客户端连接配置类
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.ssl.SSLContextBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import lombok.SneakyThrows;

@Configuration
public class ElasticSearchConfig {

	@Value("${elasticsearch.uris}")
	private String uris;
	@Value("${elasticsearch.username}")
	private String username;
	@Value("${elasticsearch.password}")
	private String password;

	@Bean(name = "restHighLevelClient")
	public RestHighLevelClient restHighLevelClient() {
		// 拆分地址
		List<HttpHost> hostLists = new ArrayList<>();
		String[] hostList = uris.split(",");
		for (String addr : hostList) {
			hostLists.add(HttpHost.create(addr));
		}
		// 转换成 HttpHost 数组
		HttpHost[] httpHost = hostLists.toArray(new HttpHost[] {});
		RestClientBuilder clientBuilder = RestClient.builder(httpHost);
		clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
			@SneakyThrows
			@Override
			public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
				if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
					CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
					UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
					credentialsProvider.setCredentials(AuthScope.ANY, credentials);
					httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
				}
				IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setIoThreadCount(100)
						.setConnectTimeout(10000).setSoTimeout(10000).build();
				httpClientBuilder.setDefaultIOReactorConfig(ioReactorConfig);
				SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
					@Override
					public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) {
						return true;
					}
				}).build();
				httpClientBuilder.setSSLContext(sslContext);
				httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
				return httpClientBuilder;
			}
		});

		return new RestHighLevelClient(clientBuilder);
	}
}

使用时注入ElasticSearchConfig:

@Autowired
RestHighLevelClient esClient;
4 基本使用

基本的使用api参考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-supported-apis.html

包含:

  • 文档操作(IndexRequest)
  • 查询操作(GetRequest)
  • 删除操作(DeleteRequest)
  • 更新操作(UpdateRequest)
  • 批量操作(BulkRequest)
  • 。。。
5 高级查询

最基本的查询写法:

SearchRequest searchRequest = new SearchRequest(); 
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 
searchRequest.source(searchSourceBuilder); 

QueryBuilders

和spring-boot-starter-data-elasticsearch的QueryBuilders同源,用法一样

多看API,熟能生巧

附:发现了一套对High Level REST Client的成熟封装代码

上传到了gitee上:https://gitee.com/zhangchaohuiget/csdn-learn/tree/master/ElasticSearchJavaClient/HignLevelClientDemo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值