要通过9300发送es,就需要与es建立一个长连接,该操作,在有api与之对应:spring-data-elasticsearch:transport-api.jar,但是我们在java中一般不会通过该端口操作,原因如下
1) springboot版本不同,transport-api.jar不同,不能适配es版本
2) 7.X已经不建议使用,8以后就要废弃
3) ES集群节点之间的通信也是使用的9300端口
通过HTTP端口发送请求,方式很多
1) JestClient:非官方,更新慢
2) RestTemplate:模拟HTTP请求,ES很多操作需要自己封装,麻烦
3) HTTPClient:同上
4)Elasticsearch-Rest-Client:官方RestClient,封装了ES操作,API层次分明,上手简单
官网(https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-api.html)截图,如下
所以,最终选择 Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client)
查看官网(https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-maven.html),可以看到依赖如下
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.10.2
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.4.2
如图:
发现ElasticSearch的版本是6.4.3,这是因为boot对elasticsearch进行了管理,如图:
所以,这里我们需要改变版本号
7.4.2
再次查看版本依赖,如图;
1)配置文件
application.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-search
2)开启服务发现与注册
1)导入依赖(已完成)
2)配置类
查看官网,如图;
所以,配置类如下:
package com.bjc.gulimall.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GulimallElasticSearchConfig {
@Bean
public RestHighLevelClient esRestClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
return client;
}
}
package com.bjc.gulimall.search;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class GulimallSearchApplicationTests {
@Autowired
private RestHighLevelClient client;
@Test
void test01() {
System.out.println(client);
}
}
测试结果:
可以打印出对象,说明可以操作client对象了。之后就可以根据官方API来进行操作es了。
打开Java High Level REST Client的api界面(https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high.html),从Getting started 开始,如图:
RequestOptions用于对所有的请求进行统一的请求头设置。
参看官网,如图:
将该段代码配置到项目中
@Configuration
public class GulimallElasticSearchConfig {
/* 通用设置项,基于默认规则 */
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();
}
@Bean
public RestHighLevelClient esRestClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
return client;
}
}
3.2.1.1 通过json字符串存储
操作步骤:
1)创建IndexRequest对象并指定post请求类型
2)设置数据id
3)获取数据的json串
4)发送请求
如图:
3.2.1.2 通过map实现
如图:
3.2.1.3 使用XContentBuilder 构造器
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.timeField("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("posts")
.id("1").source(builder);
3.2.1.4 直接利用source的键值对方式
IndexRequest indexRequest = new IndexRequest("posts")
.id("1")
.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch");
1)设置超时时间
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
2)设置等待刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
request.setRefreshPolicy("wait_for");
3)设置版本号
request.version(2);
4)设置管道
request.setPipeline("pipeline");
3.3.1 同步执行
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
3.2.3 异步执行
client.indexAsync(request, RequestOptions.DEFAULT, listener);
异步执行会有一个监听器,可以理解为js中的回调函数
listener = new ActionListener() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
@RunWith(SpringRunner.class)
@SpringBootTest
class GulimallSearchApplicationTests {
@Autowired
private RestHighLevelClient client;
@Test
public void indexTest() throws IOException {
// users 索引名称
IndexRequest request = new IndexRequest("users");
request.id("1"); // 设置数据id 如果不指定id值,就默认自增
// 组装要保存的数据
Map map = new HashMap<>();
map.put("name","张三");
map.put("age","18");
map.put("gender","F");
map.put("addr","中国");
// 要保存的内容并指定内容类型
request.source(JSONObject.toJSONString(map), XContentType.JSON);
// 使用客户端执行索引保存
IndexResponse indexResponse = client.index(request, GulimallElasticSearchConfig.COMMON_OPTIONS);
// 提取响应信息
System.out.println(indexResponse);
}
}
打印结果:
在kibana查询,结果如图
参看官网APIhttps://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high-document-get.html
根据id检索
@Autowired
private RestHighLevelClient client;
@Test
public void getTest() throws IOException {
// 参数一:索引名
// 参数二:id
GetRequest request = new GetRequest("users","1");
GetResponse getResponse = client.get(request, GulimallElasticSearchConfig.COMMON_OPTIONS);
System.out.println(getResponse);
}
参看官网:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high-search.html
参看官网实例,可以知道要做检索,需要构建一个检索请求SearchRequest
例如:
@Autowired
private RestHighLevelClient client;
@Test
public void conditionTest() throws IOException {
// 1. 构建检索请求
SearchRequest searchRequest = new SearchRequest();
// 2. 指定检索索引
searchRequest.indices("bank");
// 3.1 指定DSL内容
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 3.1.1 构建query条件
searchSourceBuilder.query(QueryBuilders.matchQuery("address","mill")); // 匹配address包含mill的雇员
// 3.1.2 构建聚合条件
// 按照age的值分布聚合,并给该次统计取一个名字aggAge
TermsAggregationBuilder aggAge = AggregationBuilders.terms("aggAge").field("age").size(10);
searchSourceBuilder.aggregation(aggAge);
// 计算平均薪资
AvgAggregationBuilder banlanceAvg = AggregationBuilders.avg("banlanceAvg").field("balance");
searchSourceBuilder.aggregation(banlanceAvg);
// 3. 创建检索条件 用于构建DSL语言
searchRequest.source(searchSourceBuilder);
// 4. 执行检索
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 5. 分析结果
// 5.1 获取所有查到的记录
SearchHits hits = searchResponse.getHits();
// 5.2 获取所有命中的记录
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
System.out.println(hit.getId());
System.out.println(hit.getSourceAsMap());
}
// 5.3 获取分析(聚合)信息
Aggregations aggregations = searchResponse.getAggregations();
Terms terms = aggregations.get("aggAge");
terms.getBuckets().forEach(item -> System.out.println("年龄:"+ item.getKeyAsString() + " total:" + item.getDocCount()));
Avg blanceAvg = aggregations.get("banlanceAvg");
System.out.println("平均薪资:" + blanceAvg.getValue());
}
结果: