Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI
引言
在上一篇 中主要介绍了 Document API,本节中讲解 search API
Search APIs
Java High Level REST Client 支持下面的 Search API:
Search API
Search Request
searchRequest
用来完成和搜索文档,聚合,建议等相关的任何操作同时也提供了各种方式来完成对查询结果的高亮操作。
最基本的查询操作如下
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加 match_all 查询
searchRequest.source(searchSourceBuilder); // 将 SearchSourceBuilder 添加到 SeachRequest 中
可选参数
SearchRequest searchRequest = new SearchRequest("posts"); // 设置搜索的 index
searchRequest.types("doc"); // 设置搜索的 type
除了配置 index
和 type
外,还有一些其他的可选参数
searchRequest.routing("routing"); // 设置 routing 参数
searchRequest.preference("_local"); // 配置搜索时偏爱使用本地分片,默认是使用随机分片
什么是 routing 参数?
当索引一个文档的时候,文档会被存储在一个主分片上。在存储时一般都会有多个主分片。Elasticsearch 如何知道一个文档应该放置在哪个分片呢?这个过程是根据下面的这个公式来决定的:
shard = hash(routing) % number_of_primary_shards
routing
是一个可变值,默认是文档的_id
,也可以设置成一个自定义的值number_of_primary_shards
是主分片数量
所有的文档 API 都接受一个叫做 routing
的路由参数,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。
使用 SearchSourceBuilder
对搜索行为的配置可以使用 SearchSourceBuilder
来完成,来看一个实例
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 默认配置
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); // 设置搜索,可以是任何类型的 QueryBuilder
sourceBuilder.from(0); // 起始 index
sourceBuilder.size(5); // 大小 size
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 设置搜索的超时时间
设置完成后,就可以添加到 SearchRequest
中。
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(sourceBuilder);
构建查询条件
查询请求是通过使用 QueryBuilder
对象来完成的,并且支持 Query DSL。
DSL (domain-specific language) 领域特定语言,是指专注于某个应用程序领域的计算机语言。
— 百度百科
可以使用构造函数来创建 QueryBuilder
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
QueryBuilder
创建后,就可以调用方法来配置它的查询选项:
matchQueryBuilder.fuzziness(Fuzziness.AUTO); // 模糊查询
matchQueryBuilder.prefixLength(3); // 前缀查询的长度
matchQueryBuilder.maxExpansions(10); // max expansion 选项,用来控制模糊查询
也可以使用QueryBuilders
工具类来创建 QueryBuilder
对象。这个类提供了函数式编程风格的各种方法用来快速创建 QueryBuilder
对象。
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
fuzzy-matching 拼写错误时的匹配:
好的全文检索不应该是完全相同的限定逻辑,相反,可以扩大范围来包括可能的匹配,从而根据相关性得分将更好的匹配放在前面。
例如,搜索
quick brown fox
时会匹配一个包含fast brown foxes
的文档
不论什么方式创建的 QueryBuilder
,最后都需要添加到 ``SearchSourceBuilder` 中
searchSourceBuilder.query(matchQueryBuilder);
构建查询 文档中提供了一个丰富的查询列表,里面包含各种查询对应的QueryBuilder
对象以及QueryBuilder
helper 方法,大家可以去参考。
关于构建查询的内容会在下篇文章中讲解,敬请期待。
指定排序
SearchSourceBuilder
允许添加一个或多个SortBuilder
实例。这里包含 4 种特殊的实现, (Field-
, Score-
, GeoDistance-
和 ScriptSortBuilder
)
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // 根据分数 _score 降序排列 (默认行为)
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC)); // 根据 id 降序排列
过滤数据源
默认情况下,查询请求会返回文档的内容 _source
,当然我们也可以配置它。例如,禁止对 _source
的获取
sourceBuilder.fetchSource(false);
也可以使用通配符模式以更细的粒度包含或排除特定的字段:
String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);
高亮请求
可以通过在 SearchSourceBuilder
上设置 HighlightBuilder
完成对结果的高亮,而且可以配置不同的字段具有不同的高亮行为。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field("title"); // title 字段高亮
highlightTitle.highlighterType("unified"); // 配置高亮类型
highlightBuilder.field(highlightTitle); // 添加到 builder
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);
聚合请求
要实现聚合请求分两步
- 创建合适的 ``AggregationBuilder`
- 作为参数配置在 ``SearchSourceBuilder` 上
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
.field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
.field("age"));
searchSourceBuilder.aggregation(aggregation);
建议请求 Requesting Suggestions
SuggestionBuilder
实现类是由 SuggestBuilders
工厂类来创建的。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
searchSourceBuilder.suggest(suggestBuilder);
对请求和聚合分析
分析 API 可用来对一个特定的查询操作中的请求和聚合进行分析,此时要将SearchSourceBuilder
的 profile标志位设置为 true
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.profile(true);
只要 SearchRequest
执行完成,对应的 SearchResponse
响应中就会包含 分析结果
同步执行
同步执行是阻塞式的,只有结果返回后才能继续执行。
SearchResponse searchResponse = client.search(searchRequest);
异步执行
异步执行使用的是 listener
对结果进行处理。
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
// 查询成功
}
@Override
public void onFailure(Exception e) {
// 查询失败
}
};
查询响应 SearchResponse
查询执行完成后,会返回 SearchResponse
对象,并在对象中包含查询执行的细节和符合条件的文档集合。
归纳一下, SerchResponse
包含的信息如下
- 请求本身的信息,如 HTTP 状态码,执行时间,或者请求是否超时
RestStatus status = searchResponse.status(); // HTTP 状态码
TimeValue took = searchResponse.getTook(); // 查询占用的时间
Boolean terminatedEarly = searchResponse.isTerminatedEarly(); // 是否由于 SearchSourceBuilder 中设置 terminateAfter 而过早终止
boolean timedOut = searchResponse.isTimedOut(); // 是否超时
- 查询影响的分片数量的统计信息,成功和失败的分片
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
检索 SearchHits
要访问返回的文档,首先要在响应中获取其中的 SearchHits
SearchHits hits = searchResponse.getHits();
SearchHits
中包含了所有命中的全局信息,如查询命中的数量或者最大分值:
long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();
查询的结果嵌套在 SearchHits
中,可以通过遍历循环获取
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// do something with the SearchHit
}
SearchHit
提供了如 index
, type
, docId
和每个命中查询的分数
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
而且,还可以获取到文档的源数据,以 JSON-String 形式或者 key-value map 对的形式。在 map 中,字段可以是普通类型,或者是列表类型,嵌套对象。
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject =
(Map<String, Object>) sourceAsMap.get("innerObject");
Search API 查询关系
上面的 QueryBuilder
, SearchSourceBuilder
和 SearchRequest
之间都是嵌套关系,为此我专门整理了一个关系图,以便更清楚的确认它们之间的关系。感兴趣的同学可用此图与前面的 API 进行对应,以加深理解。
结语
本篇包含了 Java High level Rest Client 的 SearchAPI 部分,获取高亮,聚合,分析的结果并没有在本文涉及,需要的同学可参考官方文档,下篇会包含查询构建,敬请期待~
系列文章列表
- Elasticsearch Java Rest Client API 整理总结 (一)——Document API
- Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI
- Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries
Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI的更多相关文章
- Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries
目录 上篇回顾 Building Queries 匹配所有的查询 全文查询 Full Text Queries 什么是全文查询? Match 全文查询 API 列表 基于词项的查询 Term Term ...
- Elasticsearch Java Rest Client API 整理总结 (一)——Document API
目录 引言 概述 High REST Client 起步 兼容性 Java Doc 地址 Maven 配置 依赖 初始化 文档 API Index API GET API Exists API Del ...
- Elasticsearch Java Rest Client API 整理总结 (一)
http://www.likecs.com/default/index/show?id=39549
- java微信开发API解析(二)-获取消息和回复消息
java微信开发API解析(二)-获取消息和回复消息 说明 * 本演示样例依据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/20 ...
- Elasticsearch Java Rest Client简述
ESJavaClient的历史 JavaAPI Client 优势:基于transport进行数据访问,能够使用ES集群内部的性能特性,性能相对好 劣势:client版本需要和es集群版本一致,数据序 ...
- HTML5 <Audio/>标签Api整理(二)
1.实例2: 相对较完整 Html代码: <style> #volumeSlider .slider-selection { background:#bababa; } </styl ...
- HBase Client API使用(二)---查询及过滤器
相关知识 创建表插入数据删除等见:http://www.cnblogs.com/wishyouhappy/p/3735077.html HBase API简介见:http://www.cnblogs. ...
- Java REST Client API
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-supported-apis.htm ...
- Java基础知识➣Stream整理(二)
概述 在Java数据流用到的流包括(Stream).文件(File流)和I/O流 ,利用该三个流操作数据的传输. Java控制台输入输出流 读取控制台使用数据流: BufferedReader和Inp ...
随机推荐
- C#中获取数组中相加和最接近或等于(<=)给定值的算法
, ,,,,,,,,, }; List<List<int>> mylist = new List<List<int>>(); int length = ...
- 理解 Azure 平台中虚拟机的计算能力
虚拟化平台至今已经发展了十多年的时间.其中 Hyper-V 技术现在也已经是第三代版本.用户对于虚拟化计算也越来越接受,这也有了公有云发展的基础.然而在很多时候,用户在使用基于 Hyper-V 的 A ...
- 解决MySQL5.6中的Slave延迟问题的基本教程
一.原因分析一般而言,slave相对master延迟较大,其根本原因就是slave上的复制线程没办法真正做到并发.简单说,在master上是并发模式(以InnoDB引擎为主)完成事务提交的,而在sla ...
- gh-ost和pt-osc性能对比
haughty_xiao 基于MySQL row格式的复制现在趋于主流,因此可以使用此格式的binlog来跟踪改变而不是触发器.与percona toolkit的pt-online-schem ...
- centos7 修改中文字符集
CentOS 7字符集的问题与6有点区别,会出现下面问题,查看是中文,vi进入就变成乱码了 生产中修改配置文件 [root@ce1d2002a999 ~]# cat /etc/locale.con ...
- mysql 5.7.16 忘记root 密码 如何修改root密码
今天在电脑上安装 mysql5.7.16 (压缩包)时,在初始化data文件夹之后,没有记住密码,DOS框没有显示,没办法,为了学习一下怎么修改密码,在网上找了好多方法去解决,最终还是解决了,下面来 ...
- EXI6.0的安装(找不到网卡、找不到磁盘)
给一台华为2488 V5 服务器安装EXI6.0服务 (问过华为售后不支持EXI5.5的安装,建议EXI6.0及以上版本) 根据界面提示信息按“Del”.进入BIOS设置界面 参考博客地址:https ...
- [日常] HEOI 2019 退役记
HEOI 2019 退役记 先开坑 坐等AFO 啥时候想起来就更一点(咕咕咕) Day 0 早上打了个LCT, 打完一遍过编译一遍AC...(看来不考这玩意了) 然后进行了一些精神文明建设活动奶了一口 ...
- 2018.08.31 16:26 调试 Swift 和 Pycharm 与 github 之间的链接
花了一段时间调试Swift和Pycharm的链接,网上查了一下有关信息,再加上自己的摸索,一会就掌握了.
- Alpha冲刺报告(2/12)(麻瓜制造者)
今日任务总结 燃尽图如下: 具体完成情况如下: 江郑: 今天:完成了商品需求的数据库的基本构建. 遇到的问题:对于php的ci框架不熟,操作原理不懂 明天:和队友进行数据库的对接 符天愉: 今天:完成 ...