文章目录
1 准备工作
- 依赖
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
</dependencies>
- 准备索引库
PUT books
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"id":{
"type": "long"
},
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"language":{
"type": "keyword"
},
"author":{
"type": "keyword"
},
"price":{
"type": "double"
},
"publish_time":{
"type": "date",
"format": "yyyy-MM-dd"
},
"description":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
2 前置API介绍
2.1 如何构建高级客户端
@Test
public void buildHighClient() throws IOException {
// 可见高级客户端的构建也是基于低级客户端构建,可以大胆猜测高级客户端就是对低级客户端的包装
// 对外暴露的API对使用者来说更加友好
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
restHighLevelClient.close();
}
2.2 如何构建json文档(数据)
es,提供了一下几个方式来构建json格式的数据
- json格式的字符串
- 使用Map,es会自动把他转换成一个json数据
- 使用XContentFactory.jsonBuilder来构建json
/****
* 直接使用字符串形式
*/
@Test
public void testString(){
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("1");
// String 类型文档
String json = "{\n" +
" \"id\":\"1\",\n" +
" \"title\":\"Java编程思想\",\n" +
" \"language\":\"java\",\n" +
" \"author\":\"Bruce Eckel\",\n" +
" \"price\":70.2,\n" +
" \"publish_time\":\"2007-10-01\",\n" +
" \"description\":\"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。\"\n" +
"}";
request.source(json, XContentType.JSON);
}
/****
* 使用Map构建
*
*/
@Test
public void testMap(){
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("2");
Map<String,Object> mappings = new HashMap<>();
mappings.put("id",2L);
mappings.put("title","Java程序性能优化");
mappings.put("language","java");
mappings.put("author","葛一鸣");
mappings.put("price",45.60f);
mappings.put("publish_time",new Date());
mappings.put("description","让你的Java程序更快、更稳定。深入剖析软件设计层面、代码层面、JVM虚拟机层面的优化方法");
request.source(mappings);
}
/****
* 使用Map构建
*
*/
@Test
public void testXContentBuilder() throws IOException {
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("3");
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
// startObject 构建对象,可以理解为json中的{
// startArray:构建数组,可以理解为json中的[
xContentBuilder.startObject();
xContentBuilder.field("id",3L);
xContentBuilder.field("title","Python科学计算");
xContentBuilder.field("language","python");
xContentBuilder.field("author","张若愚");
xContentBuilder.field("price",81.40f);
xContentBuilder.field("publish_time",new Date());
xContentBuilder.field("description","零基础学python,光盘中作者独家整合开发winPython运行环境,涵盖了Python各个扩展库");
// endObject 可以理解为json中的}
xContentBuilder.endObject();
request.source(xContentBuilder);
}
3 索引文档
整体步骤:
- 构建请求参数:IndexRequest
- 执行请求
- 同步执行
- 异步执行
- 解析响应结果: IndexResponse
3.1 如何构建IndexRequest
必填的参数:
- 索引库名:
- 文档id
- 文档内容:json格式,如何构建上面已经介绍了
几个可选参数:这些都可以对应到es提供的restAPI,可以去翻看前面的RestAPI介绍
- 超时时间
- 超时策略
- 设置路由
- 设置版本号,版本类型
- 设置操作类型
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("1");
// 设置超时时间
request.timeout(TimeValue.timeValueSeconds(1L));
// request.timeout("1s");
// 设置超时策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
// 设置版本
request.version(1);
// 设置版本类型
request.versionType(VersionType.EXTERNAL);
// 设置操作类型
//request.opType("create");
request.opType(DocWriteRequest.OpType.CREATE);
3.2 执行请求
3.2.1 同步执行
同步执行,客户端就会阻塞,直到es服务端返回请求结果。
API:
public class RestHighLevelClient implements Closeable {
public final IndexResponse index(IndexRequest indexRequest, RequestOptions options)
}
- 同步执行的时候可能会出现io异常,比如请求超时,客户端会抛出IOException
- es服务端返回4XX或者5XX错误码的时候,客户端会尝试解析响应报文中的错误信息,并且抛出一个ElasticsearchException
// 同步执行执行请求
try {
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
3.2.2 异步执行
异步执行,需要配置一个监听器ActionListener
,用于监听es响应结果:
public final Cancellable indexAsync(IndexRequest indexRequest, RequestOptions options, ActionListener<IndexResponse> listener) {
return performRequestAsyncAndParseEntity(indexRequest, RequestConverters::index, options, IndexResponse::fromXContent, listener,
emptySet());
}
// 异步执行
client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
// 执行成功的回调
@Override
public void onResponse(IndexResponse indexResponse) {
}
// 执行失败的回调
@Override
public void onFailure(Exception e) {
}
});
3.3 解析响应结果
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
// 响应状态
RestStatus status = response.status();
log.info("响应状态: {}",status);
// 获取文档id
String id = response.getId();
// 获取文档索引
String index = response.getIndex();
log.info("文档索引库: {}; 文档id: {}",index,id);
// 获取结果: 枚举值:创建,删除,更新,not find
// 对于此处来说,只能是创建或者是更新,es当id存在的时候就是执行更新,id不存在就是创建,和restAPI是一样的
DocWriteResponse.Result result = response.getResult();
log.info("响应结果: {}",result);
// 获取分片信息
ReplicationResponse.ShardInfo shardInfo = response.getShardInfo();
log.info("分片信息: {}",shardInfo);
// 获取文档版本
long version = response.getVersion();
log.info("文档版本号: {}",version);
3.4 完整的一个测试代码
public abstract class BaseTest {
public static RestHighLevelClient client;
static {
client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
}
}
package study.wyy.esclient.high.document;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.rest.RestStatus;
import org.junit.Test;
import study.wyy.esclient.high.BaseTest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author wyaoyao
* @description
* @date 2021/1/8 16:32
*/
@Slf4j
public class BuildJsonDocumentTest extends BaseTest {
/****
* 直接使用字符串形式,测试同步执行,和响应结果的解析
*/
@Test
public void testString() throws IOException {
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("1");
// String 类型文档
String json = "{\n" +
" \"id\":\"1\",\n" +
" \"title\":\"Java编程思想\",\n" +
" \"language\":\"java\",\n" +
" \"author\":\"Bruce Eckel\",\n" +
" \"price\":70.2,\n" +
" \"publish_time\":\"2007-10-01\",\n" +
" \"description\":\"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。\"\n" +
"}";
request.source(json, XContentType.JSON);
// 设置超时时间
request.timeout(TimeValue.timeValueSeconds(1L));
// request.timeout("1s");
// 设置超时策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
// 设置版本
//request.version(2);
// 设置版本类型
//request.versionType(VersionType.EXTERNAL);
// 设置操作类型
//request.opType("create");
request.opType(DocWriteRequest.OpType.CREATE);
// 同步执行执行请求
try {
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
// 响应状态
RestStatus status = response.status();
log.info("响应状态: {}",status);
// 获取文档id
String id = response.getId();
// 获取文档索引
String index = response.getIndex();
log.info("文档索引库: {}; 文档id: {}",index,id);
// 获取结果: 枚举值:创建,删除,更新,not find
// 对于此处来说,只能是创建或者是更新,es当id存在的时候就是执行更新,id不存在就是创建,和restAPI是一样的
DocWriteResponse.Result result = response.getResult();
log.info("响应结果: {}",result);
// 获取分片信息
ReplicationResponse.ShardInfo shardInfo = response.getShardInfo();
log.info("分片信息: {}",shardInfo);
// 获取文档版本
long version = response.getVersion();
log.info("文档版本号: {}",version);
} catch (Exception e) {
e.printStackTrace();
}finally {
client.close();
}
}
/****
* 使用Map构建,并测试异步执行
*
*/
public static void testMap(){
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("2");
Map<String,Object> mappings = new HashMap<>();
mappings.put("id",2L);
mappings.put("title","Java程序性能优化");
mappings.put("language","java");
mappings.put("author","葛一鸣");
mappings.put("price",45.60f);
mappings.put("publish_time",new Date());
mappings.put("description","让你的Java程序更快、更稳定。深入剖析软件设计层面、代码层面、JVM虚拟机层面的优化方法");
request.source(mappings);
// 异步执行
client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
// 执行成功的回调
@Override
public void onResponse(IndexResponse indexResponse) {
log.info("成功");
}
// 执行失败的回调
@Override
public void onFailure(Exception e) {
log.info("失败");
}
});
}
/****
* 使用XContentBuilder构建
*
*/
@Test
public void testXContentBuilder() throws IOException {
// 索引的名字
IndexRequest request = new IndexRequest("books");
// 设置文档id, 也可以不设置es会自动生成一个
request.id("3");
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
// startObject 构建对象,可以理解为json中的{
// startArray:构建数组,可以理解为json中的[
xContentBuilder.startObject();
xContentBuilder.field("id",3L);
xContentBuilder.field("title","Python科学计算");
xContentBuilder.field("language","python");
xContentBuilder.field("author","张若愚");
xContentBuilder.field("price",81.40f);
xContentBuilder.field("publish_time",new Date());
xContentBuilder.field("description","零基础学python,光盘中作者独家整合开发winPython运行环境,涵盖了Python各个扩展库");
// endObject 可以理解为json中的}
xContentBuilder.endObject();
request.source(xContentBuilder);
IndexResponse index = client.index(request, RequestOptions.DEFAULT);
client.close();
}
public static void main(String[] args) {
testMap();
}
}
响应结果日志打印:
响应状态: CREATED
文档索引库: books; 文档id: 1
响应结果: CREATED
分片信息: ShardInfo{total=2, successful=1, failures=[]}
kibana: 查看是否三个文档已经存在
GET books/_search
{
"query": {
"match_all": {}
}
}
{
"took" : 12,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "books",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"author" : "葛一鸣",
"price" : 45.6,
"publish_time" : "2021-01-11T02:47:27.580Z",
"description" : "让你的Java程序更快、更稳定。深入剖析软件设计层面、代码层面、JVM虚拟机层面的优化方法",
"language" : "java",
"id" : 2,
"title" : "Java程序性能优化"
}
},
{
"_index" : "books",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"id" : 3,
"title" : "Python科学计算",
"language" : "python",
"author" : "张若愚",
"price" : 81.4,
"publish_time" : "2021-01-11T02:48:05.585Z",
"description" : "零基础学python,光盘中作者独家整合开发winPython运行环境,涵盖了Python各个扩展库"
}
},
{
"_index" : "books",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"id" : "1",
"title" : "Java编程思想",
"language" : "java",
"author" : "Bruce Eckel",
"price" : 70.2,
"publish_time" : "2007-10-01",
"description" : "Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。"
}
}
]
}
}