Elasticsearch-Rest-Client
通过 9300: TCP
spring-data-elasticsearch:transport-api.jar;
jestClient: 非官方,更新慢;
- RestTemplate:模拟HTTP请求,ES很多操作需要自己封装,麻烦;
- HttpClient:同上;
- Elasticsearch-Rest-Client:官方RestClient,封装了ES操作,API层次分明,上手简单;
最终选择 Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client); https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
创建 Elasticsearch 检索服务模块
新建模块


pom.xml
<properties><java.version>1.8</java.version><!-- SpringBoot管理了elasticsearch的版本, 所有我们需要重写这个版本 --><elasticsearch.version>7.4.2</elasticsearch.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 用来转换JSON数据 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency></dependencies>
编码测试
具体操作参考:es 操作API
编写配置类
package org.hong.gulimall.search.config;import org.apache.http.HttpHost;import org.elasticsearch.client.RequestOptions;import org.elasticsearch.client.RestClient;import org.elasticsearch.client.RestHighLevelClient;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class ElasticsearchConfig {/*** 配置请求选项* 参考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low-usage-requests.html#java-rest-low-usage-request-options*/public static final RequestOptions COMMON_OPTIONS;static {RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();// builder.addHeader("Authorization", "Bearer " + TOKEN);// builder.setHttpAsyncResponseConsumerFactory(// new HttpAsyncResponseConsumerFactory// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));COMMON_OPTIONS = builder.build();}@Beanpublic RestHighLevelClient esRestClient() {return new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.200.130", 9200, "http")));}}
测试配置类依赖注入
package org.hong.gulimall.search;import org.elasticsearch.client.RestHighLevelClient;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestclass GulimallSearchApplicationTests {@AutowiredRestHighLevelClient client;@Testvoid contextLoads() {System.out.println(client);}}
测试存储数据 ( 更新 )
参考:Index API
package org.hong.gulimall.search;import com.alibaba.fastjson.JSON;import lombok.Data;import org.elasticsearch.action.index.IndexRequest;import org.elasticsearch.action.index.IndexResponse;import org.elasticsearch.client.RestHighLevelClient;import org.elasticsearch.common.xcontent.XContentType;import org.hong.gulimall.search.config.ElasticsearchConfig;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;@SpringBootTestclass GulimallSearchApplicationTests {@AutowiredRestHighLevelClient client;@Dataclass User{private String userName;private String gender;private Integer age;}@Testvoid indexData() throws IOException {// 创建IndexRequest对象IndexRequest indexRequest = new IndexRequest();// 设置indexindexRequest.index("users");// 设置idindexRequest.id("1");// 准备需要保存的数据User user = new User();user.setUserName("hong");user.setAge(18);user.setGender("男");// 将对象转换成JSON格式的数据String jsonString = JSON.toJSONString(user);// 设置资源indexRequest.source(jsonString, XContentType.JSON);// 执行操作IndexResponse index = client.index(indexRequest, ElasticsearchConfig.COMMON_OPTIONS);// 提取有用的响应数据System.out.println(index);}}
控制台打印
IndexResponse[index=users,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
Kibana 检索查看
GET /users/_search
{"took" : 4,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "users","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"age" : 18,"gender" : "男","userName" : "hong"}}]}}
测试复杂检索
参考: Search API
检索地址中带有 mill 的人员年龄分布和平均薪资
package org.hong.gulimall.search;import com.alibaba.fastjson.JSON;import lombok.Data;import org.elasticsearch.action.search.SearchRequest;import org.elasticsearch.action.search.SearchResponse;import org.elasticsearch.client.RestHighLevelClient;import org.elasticsearch.index.query.QueryBuilders;import org.elasticsearch.search.SearchHit;import org.elasticsearch.search.SearchHits;import org.elasticsearch.search.aggregations.AggregationBuilders;import org.elasticsearch.search.aggregations.Aggregations;import org.elasticsearch.search.aggregations.bucket.terms.Terms;import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;import org.elasticsearch.search.aggregations.metrics.Avg;import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;import org.elasticsearch.search.builder.SearchSourceBuilder;import org.hong.gulimall.search.config.ElasticsearchConfig;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;@SpringBootTestclass GulimallSearchApplicationTests {@AutowiredRestHighLevelClient client;@Datastatic class Account {private int account_number;private int balance;private String firstname;private String lastname;private int age;private String gender;private String address;private String employer;private String email;private String city;private String state;}@Testvoid searchData() throws IOException {// 1、创建检索请求SearchRequest searchRequest = new SearchRequest();// 指定索引searchRequest.indices("bank");// 指定DSL, 检索条件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 1.1、构造检索条件 address 包含 millsearchSourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));// 1.2 按照年龄值分布进行聚合TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(100);// 嵌套聚合subAggregation()方法//ageAgg.subAggregation(AggregationBuilders.avg("balanceAvg").field("balance"));searchSourceBuilder.aggregation(ageAgg);// 1.3 计算平均薪资AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");searchSourceBuilder.aggregation(balanceAvg);searchRequest.source(searchSourceBuilder);System.out.println(searchSourceBuilder);// 2、执行检索SearchResponse searchResponse = client.search(searchRequest, ElasticsearchConfig.COMMON_OPTIONS);// 3、分析结果System.out.println(searchResponse);// 3.1、获取所有查询到的数据SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit searchHit : searchHits) {// 获取JSON格式的数据String sourceAsString = searchHit.getSourceAsString();Account account = JSON.parseObject(sourceAsString, Account.class);System.out.println(account);}// 3.2、获取检索到的分析信息Aggregations aggregations = searchResponse.getAggregations();Terms ageAgg1 = aggregations.get("ageAgg");for (Terms.Bucket bucket : ageAgg1.getBuckets()) {System.out.println("年龄:" + bucket.getKey() + "\t" + "数量:" + bucket.getDocCount());}Avg avgBalance = aggregations.get("balanceAvg");System.out.println("平均薪资:" + avgBalance.getValue());}}
