文档章节

Elasitcsearch High Level Rest Client学习笔记(二) 基础API

木子SMZ
 木子SMZ
发布于 2018/07/17 15:02
字数 2372
阅读 415
收藏 1

1、index API

IndexRequest request = new IndexRequest(
        "posts", //index
        "doc",   //type 类型,我对类型的理解有点类似于数据库中的表   index类似于数据库中的database
        "1");    //Document Id
String jsonString = "{" +
        "\"user\":\"kimchy\"," +
        "\"postDate\":\"2013-01-30\"," +
        "\"message\":\"trying out Elasticsearch\"" +
        "}";
request.source(jsonString, XContentType.JSON);  //source可以有多种形式下面介绍

 

source可以以map的形式提供,查看官方文档介绍map形式提供的source会自动转换成json格式,初步观察源代码,写的还挺复杂,简单过了一遍其实没太懂,大概意思是map->XContentBuilder,XContentBuilder通过内置工具生成json

Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch");
IndexRequest indexRequest = new IndexRequest("posts", "doc", "1")
        .source(jsonMap);

 

source也可以以XContentBuilder形式提供,通过 Elasticsearch built-in helpers生产恒json

XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
    builder.field("user", "kimchy");
    builder.field("postDate", new Date());
    builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("posts", "doc", "1")
        .source(builder);

 

source也可以以Object key-value形式提供,依然转换成json

IndexRequest indexRequest = new IndexRequest("posts", "doc", "1")
        .source("user", "kimchy",
                "postDate", new Date(),
                "message", "trying out Elasticsearch");

 

其他可选参数

设置路由,说起这个方法要介绍一下路由的概念,elasticsearch 路由机制

request.routing("routing");

 

parent,es的parent-child结构,简单点说是一对多的关系,es多对多情况要拆分成一对多;限制是parent和children必须在同一个shard当中,当添加文档时指定了parent后,就不会用默认的本文档id分配路由,而是采用父文档的路由值,保证父文档和子文档处于同一个shard当中。需要注意的是,查询时需要指定路由,否则查询会出错。当大于等于三级时,需要指定最顶层父节点路由,以让文档存储在用一个shard中。

request.parent("parent");

 

设置超时时间,有两种形式, TimeValue 或者字符串

request.timeout(TimeValue.timeValueSeconds(1)); 
request.timeout("1s");

 

设置刷新策略, WriteRequest.RefreshPolicy 或者字符串

request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for");

 

版本号,好像是文档版本,类似于乐观锁的东西吧,没验证,验证后更新

request.version(2);

 

操作类型,当设置create时,并且指定index、type和id存在,不会更新文档,会抛出异常

request.opType(DocWriteRequest.OpType.CREATE); 
request.opType("create");

 

同步调用方式,没什么可说的

IndexResponse indexResponse = client.index(request);

异步调用方式,需要传入一个监听接口,通知结果或者接受异常

client.indexAsync(request, new ActionListener<IndexResponse>() {
    @Override
    public void onResponse(IndexResponse indexResponse) {
        //成功后执行代码,响应结果以参数传入
    }

    @Override
    public void onFailure(Exception e) {
       //失败时执行代码,异常以参数传入
    }
});

响应结果

响应结果官方示例代码如下

String index = indexResponse.getIndex();
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
    //文档不存在,创建后处理代码
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
    、、//
/////文档被更新
}
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
    //成功shard数量小于总数
}
if (shardInfo.getFailed() > 0) {
    for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
        String reason = failure.reason(); 
        //处理可能存在的失败
    }
}

异常处理

文档发生版本冲突

IndexRequest request = new IndexRequest("posts", "doc", "1")
        .source("field", "value")
        .version(1);
try {
    IndexResponse response = client.index(request);
} catch(ElasticsearchException e) {
    if (e.status() == RestStatus.CONFLICT) {
        //版本冲突处理代码
    }
}

设置opType=create,并且指定index、type和id存在,不会更新文档,会抛出异常

IndexRequest request = new IndexRequest("posts", "doc", "1")
        .source("field", "value")
        .opType(DocWriteRequest.OpType.CREATE);
try {
    IndexResponse response = client.index(request);
} catch(ElasticsearchException e) {
    if (e.status() == RestStatus.CONFLICT) {
         //处理代码
    }
}

2、get api

GetRequest getRequest = new GetRequest(
        "posts", //index
        "doc",  //type
        "1");     //document id

可变参数

禁用获取源数据(source),默认开启。先要理解什么是源数据,_source字段,保存存储是的json body

request.fetchSourceContext(new FetchSourceContext(false));

 

设置检索返回字段和检索排除字段,同时试了一下即包含又排除的字段,排除有限,既包含又排斥的座位排斥字段

String[] includes = new String[]{"message", "*Date"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"message"};
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);

 

设置返回指定存储字段(我是这样理解的,不过我测试失败了,设置了存储字段之后,还是不能像例子一样获取值)

request.storedFields("message"); 
GetResponse getResponse = client.get(request);
String message = getResponse.getField("message").getValue();

 

设置路由,parent-child查询时需要指定路由

request.routing("routing");

 

设置查询父节点,在get查询时,不理解为什么需要设置parent,我测试了一下发现没什么用,不管设置的parent是不是正确的parent,都能查询出结果,这个应该是一个通用方法吧,在get中可能没有用到

request.parent("parent");

 

elasticsearch可以使用preference参数来指定分片查询的优先级,即我们可以通过该参数来控制搜索时的索引数据分片。如不设置该参数:在所有有效的主分片以及副本间轮询

没太理解,所以没测试

request.preference("preference");

 

设置实时查询开启/关闭,默认为true。

通过查询资料,real-time是es的一种方式,也是新文档索引模型,跟这个api好像关系不大,这个api不是很理解,我本地集群数据比较少,true/false没发现太大区别;es通过fsync把数据写入到磁盘中,fsync十分消耗资源,es的实时查询瓶颈在硬盘读写,es利用文件系统缓存来加快实时查询速度。具体资料:

大牛博客:https://www.jianshu.com/p/94ce44d6a802

官方文档:https://www.elastic.co/guide/en/elasticsearch/guide/current/near-real-time.html

request.realtime(false);

 

设置查询前执行刷新,默认false,每个shard默认1秒钟一次refresh

request.refresh(true);

 

版本号,不多解释

request.version(2);

 

调用方式

同步

GetResponse getResponse = client.get(getRequest);

异步

client.getAsync(request, new ActionListener<GetResponse>() {
    @Override
    public void onResponse(GetResponse getResponse) {
        //成功
    }

    @Override
    public void onFailure(Exception e) {
        //失败
    }
});

响应对象

GetResponse查询请求文档及其源数据以及最终存储字段

String index = getResponse.getIndex();
String type = getResponse.getType();
String id = getResponse.getId();
if (getResponse.isExists()) {
    long version = getResponse.getVersion();
    String sourceAsString = getResponse.getSourceAsString();        //字符串形式
    Map<String, Object> sourceAsMap = getResponse.getSourceAsMap(); //Map形式
    byte[] sourceAsBytes = getResponse.getSourceAsBytes();          //字节数组形式
} else {
    //处理找不到文档代码。注意返回的是404状态而不是异常,
}

异常处理

如果需要捕获异常,需要try catch代码块包裹,ElasticsearchException是runtime exception

GetRequest request = new GetRequest("does_not_exist", "doc", "1");
try {
    GetResponse getResponse = client.get(request);
} catch (ElasticsearchException e) {
    if (e.status() == RestStatus.NOT_FOUND) {
        //处理文档不存在情况
    }
}

指定版本号,版本号冲突情况

try {
    GetRequest request = new GetRequest("posts", "doc", "1").version(2);
    GetResponse getResponse = client.get(request);
} catch (ElasticsearchException exception) {
    if (exception.status() == RestStatus.CONFLICT) {
        //版本号冲突
    }
}

3、delete api

如果存在parent的type,需要指定路由(route)

异步调用测试失败,按照官方文档,不管成功还是失败均没捕获到断点

DeleteRequest request = new DeleteRequest(
        "posts",    //index
        "doc",     //type
        "1");      //id

调用方式

同步

DeleteResponse deleteResponse = client.delete(request);

异步

client.deleteAsync(request, new ActionListener<DeleteResponse>() {
    @Override
    public void onResponse(DeleteResponse deleteResponse) {
        //成功
    }

    @Override
    public void onFailure(Exception e) {
        //失败
    }
});

响应对象

返回操作信息,如下

String index = deleteResponse.getIndex();
String type = deleteResponse.getType();
String id = deleteResponse.getId();
long version = deleteResponse.getVersion();
ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
    //成功shard数量小于总数
}
if (shardInfo.getFailed() > 0) {
    for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
        String reason = failure.reason(); //处理潜在的错误
    }
}

删除文档不存在情况

DeleteRequest request = new DeleteRequest("posts", "doc", "does_not_exist");
DeleteResponse deleteResponse = client.delete(request);
if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
    //删除文档不存在
}

异常处理

版本号冲突

try {
    DeleteRequest request = new DeleteRequest("posts", "doc", "1").version(2);
    DeleteResponse deleteResponse = client.delete(request);
} catch (ElasticsearchException exception) {
    if (exception.status() == RestStatus.CONFLICT) {
        //版本冲突
    }
}

4、update api

UpdateRequest request = new UpdateRequest(
        "posts", //index
        "doc",  //type
        "1");    //document id

painless script暂时不写,没搞明白语法

源数据格式(其实都是转换成json格式)

UpdateRequest request = new UpdateRequest("posts", "doc", "1");
String jsonString = "{" +
        "\"updated\":\"2017-01-01\"," +
        "\"reason\":\"daily update\"" +
        "}";
request.doc(jsonString, XContentType.JSON); //json格式
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("updated", new Date());
jsonMap.put("reason", "daily update");
UpdateRequest request = new UpdateRequest("posts", "doc", "1")
        .doc(jsonMap); //map格式
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
    builder.field("updated", new Date());
    builder.field("reason", "daily update");
}
builder.endObject();
UpdateRequest request = new UpdateRequest("posts", "doc", "1")
        .doc(builder); //XContentBuilder
UpdateRequest request = new UpdateRequest("posts", "doc", "1")
        .doc("updated", new Date(),
             "reason", "daily update"); //object key-pairs

upserts(save or update)

当文档不存在时,以新文档插入

String jsonString = "{\"created\":\"2017-01-01\"}";
request.upsert(jsonString, XContentType.JSON);

可变参数

设置路由,路由什么意思,前一篇文章介绍过

request.routing("routing");

 

设置父节点

request.parent("parent");

 

两种形式的超时设置

request.timeout(TimeValue.timeValueSeconds(1)); 
request.timeout("1s");

 

设置刷新策略

request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for");

 

冲突尝试次数

request.retryOnConflict(3);

 

是否返回源数据,默认false

request.fetchSource(true);

 

指定包含字段或者排除字段,重叠时排除字段优先

String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(new FetchSourceContext(true, includes, excludes));
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
request.fetchSource(new FetchSourceContext(true, includes, excludes));

 

数据版本号

request.version(2);

 

noop检测。我的理解是返回状态值

request.detectNoop(false);

调用方式

同步

UpdateResponse updateResponse = client.update(request);

异步

client.updateAsync(request, new ActionListener<UpdateResponse>() {
    @Override
    public void onResponse(UpdateResponse updateResponse) {
        //成功
    }

    @Override
    public void onFailure(Exception e) {
        //失败
    }
});

响应对象

String index = updateResponse.getIndex();
String type = updateResponse.getType();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
    (upserts)首次创建对象
} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
    //文档被更新
} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
    //文档被删除
} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
    //没有
}

设置返回源数据,回去返回的源数据

GetResult result = updateResponse.getGetResult(); //以GetResult格式返回更新后的文档
if (result.isExists()) {
    String sourceAsString = result.sourceAsString(); //字符串形式返回更新后文档源数据
    Map<String, Object> sourceAsMap = result.sourceAsMap(); //map形式
    byte[] sourceAsBytes = result.source(); //字节形式
} else {
    //默认情况下,源数据在响应对象中返回
}

shard异常

ReplicationResponse.ShardInfo shardInfo = updateResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
     //成功数量小于总数
}
if (shardInfo.getFailed() > 0) {
    for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
        String reason = failure.reason();  //处理可能的异常
    }
}

版本号冲突情况

pdateRequest request = new UpdateRequest("posts", "doc", "1")
        .doc("field", "value")
        .version(1);
try {
    UpdateResponse updateResponse = client.update(request);
} catch(ElasticsearchException e) {
    if (e.status() == RestStatus.CONFLICT) {
        //处理版本号冲突情况
    }
}

© 著作权归作者所有

木子SMZ
粉丝 2
博文 34
码字总数 22804
作品 0
昌平
程序员
私信 提问
Elasitcsearch High Level Rest Client学习笔记(一)

文档地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.1/java-rest-high.html java doc地址: https://artifacts.elastic.co/javadoc/org/elasticsearch/client/el......

木子SMZ
2018/07/12
0
0
Elasticsearch Java Rest Client 上手指南(下)

High Level Rest Clent到现在还不是完成版。我试了一下,5.6版本的就这么些API 包含了基本的增删改查和批量操作 我翻了一下官方文档,凉凉。确实像官方文档说的那样,需要完善。虽然是High ...

MaxZing
2018/07/18
0
0
High Level REST Client 访问阿里云6.3 Elasticsearch 实例实现

开发环境:InteliJ IDEA 操作系统 :macOS Mojave Elasticsearch 版本:阿里云 6.3.2withX-Pack 客户端版本:REST Client 6.3.2 1. 预先创建好阿里云 ES 实例,开启公网地址访问白名单。 2....

garygao305
01/15
0
0
Elasticsearch Java Rest Client 上手指南(上)

开始看Elasticsearch Java API 的时候,被这段话浇了盆凉水 We plan on deprecating the in Elasticsearch 7.0 and removing it completely in 8.0. Instead, you should be using the Java......

MaxZing
2018/07/17
0
0
ES(elasticsearch)搜索引擎

ES(elasticsearch)搜索引擎 0、授人以渔,少走半年弯路! 死磕 Elasticsearch 方法论:普通程序员高效精进的 10 大狠招! 一、Elasitcsearch基础篇 1.1 Elasitcsearch基础认知 1、Elasticse...

Ocean_K
2018/09/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

访问LNMP虚拟主机出现报错:No input file specified.

之前一直是使用lnmp一键包,但是访问创建的虚拟主机,并没有出现过的错误:No input file specified. 网上的文章很多,但是都是转载,而且原因也很多,根本不适用 后面在lnmp一键包官网找到解...

wenzhizhong
31分钟前
1
0
OSChina 周三乱弹 —— 你还能管得住观众愿意看谁吗

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享李宗盛的单曲《凡人歌 (电视剧《碧海情天》主题曲)》:你我皆凡人,生在人世间#今日歌曲推荐# 《凡人歌 (电视剧《碧海情天》主...

小小编辑
54分钟前
372
12
Inf2Cat, signability test failed vc2019 wdk驱动sys build签名

解决问题的方法非常简单,只要让Inf2Cat验证的时候使用local时间就可以了。打开package工程的属性,在inf2cat工具的属性中进行设置。

simpower
今天
3
0
LinkedHashMap 是如何保证有序的?

//map的遍历方法如下 for (Map.Entry<String,Integer> entry : map.entrySet()) { System.out.println(entry.getKey()+":"+entry.getValue()); } HashMap#entry......

暗中观察
今天
3
0
Linux的基本命令

目录的操作命令(增删改查) 增: mkdir 目录名称; 查: ls 可以看到该目录下的所有的目录和文件 ls -a,可以看到该目录下的所有文件和目录,包括隐藏的 ls -l,可以看到该目录下的所有目录和...

凹凸凸
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部