博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES_记一次分页查询(getHits().getTotalHits() 获取总条目)为0的问题
阅读量:3937 次
发布时间:2019-05-23

本文共 3567 字,大约阅读时间需要 11 分钟。

问题描述

ES分页查询的代码如下:

SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);long totalNum = searchResponse.getHits().getTotalHits();   //返回的是long型的SearchHit[] searchHits = searchResponse.getHits().getHits();

随着ES server 集群升级以后(从5.5.1->7.5.1),自动化脚步跑失败了,因为ES集群升级后totalNum的值为0了,哪怕searchHits 明明有数据

问题原因

既然使用High Level Client的Java api 查询有问题,那么直接通过http rest接口从ES 集群查询,结果如下,发现是有total是有数据而且大于0的

在这里插入图片描述
细细一看,发现Java客户端中getHits().getTotalHits()的返回类型是long型的,但是上面的截图中,还有relation这样的额外字段。searchResponse.getHits()的返回类型为SearchHits。于是确认本地ES 客户端版本为6.7.1后,对比这两个版本的SearchHits,结果如下:

7.5.1

public final class SearchHits {
private final SearchHit[] hits; private final TotalHits totalHits; //看这里 private final float maxScore;}

6.7.1

public final class SearchHits {
private SearchHit[] hits; public long totalHits; //看这里 private float maxScore;}

果然两个版本的SearchHits 类的totalHits 字段类型不一样了,那么6.7.1的客户端在Json转对象的时候,当然不能拿正常赋值,所以totalHits 就是默认的0值

解决办法查找

既然问题的原因找到了,那么怎么解决呢,我的第一想法就是客户端也升级为何集群一样的版本。正准备去尝试的时候,发现了一个问题。请各位胖友仔细观察前面Http rest 直接查询的结果和SearchHits对象的字段名字,把它们对比一下.有如下现象:

total -> totalHits

max_score -> maxScore

基于我们对Json 反序列,和反射的理解,Json字符串的key应该和对象字段名字一一对应才对,那么到底是哪儿在帮着转化处理了呢?

通过搜索在7.5.1的SearchHits这个类的toXContent方法中我找到了答案。图中提示的地方做了字段名字的转换。
在这里插入图片描述
各位胖友在仔细看看toXContent方法中的这段代码:

boolean totalHitAsInt = params.paramAsBoolean(RestSearchAction.TOTAL_HITS_AS_INT_PARAM, false); if (totalHitAsInt) {
//按照老的方式处理,直接是long型的totalHits long total = totalHits == null ? -1 : totalHits.value; builder.field(Fields.TOTAL, total); } else if (totalHits != null) {
builder.startObject(Fields.TOTAL); builder.field("value", totalHits.value); builder.field("relation", totalHits.relation == Relation.EQUAL_TO ? "eq" : "gte"); builder.endObject(); }

这段代码也比较明了,基于RestSearchAction.TOTAL_HITS_AS_INT_PARAM(rest_total_hits_as_int)这个参数来控制,当值为true时totalHits以int类型返回。

在Http rest接口我加这个参数试了试,还真可以解决问题,结果如下:
在这里插入图片描述
当我以为不用升级客户端版本了,只需要在High Level Client的api调用中加入上面的那个参数,就能解决问题的时候,“屁颠屁颠”的在High Level Client的api中找添加Http参数调用的接口,好一阵才发现似乎并没有接口来添加Http参数。看来此路不通,继续想办法。

一路进入highLevelClient.search的源码,我发现ES其实是处理了Http参数的添加的,如下:

//org.elasticsearch.client.RequestConverters#addSearchRequestParams    private static void addSearchRequestParams(RequestConverters.Params params, SearchRequest searchRequest) {
params.putParam("typed_keys", "true"); params.withRouting(searchRequest.routing()); params.withPreference(searchRequest.preference()); params.withIndicesOptions(searchRequest.indicesOptions()); params.putParam("search_type", searchRequest.searchType().name().toLowerCase(Locale.ROOT)); if (searchRequest.requestCache() != null) {
params.putParam("request_cache", Boolean.toString(searchRequest.requestCache())); } if (searchRequest.allowPartialSearchResults() != null) {
params.putParam("allow_partial_search_results", Boolean.toString(searchRequest.allowPartialSearchResults())); } .......等等

因为ES客户端在请求的时候,会把SearchRequest转化为Request,而这个Request中是可以放参数的。

但是它只是自己加了一些参数,而且似乎并没有给我们预留接口呀。

最终一番查找资料之后,在ES的github Pull Request中找到了说明。详情点击这里

截图如下:
在这里插入图片描述
意思就是在6.8版本后,把rest_total_hits_as_int参数加入请求中。怎么加的呢,如下:

在这里插入图片描述

到了这里,整个过程已经很明了了,那么解决办法也呼之欲出,我本地把客户端版本升到6.8.4,问题解决。

总结

高版本的ES集群,可以使用参数rest_total_hits_as_int来让totalHits字段,仍然以int格式返回。
ES更新很快,一定要注意版本问题带来的坑,最好让集群和客户端使用官方推荐的匹配版本。
结束语
如果胖友发现文章有不对或者不妥之处,还望在评论中不吝指出^ v ^。
————————————————
版权声明:本文为CSDN博主「two_penguin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/daofengsuoxiang/article/details/104776085/

你可能感兴趣的文章
Operators and special characters in matlab
查看>>
As-Conformal-As-Possible Surface Registration
查看>>
qmake Variable Reference
查看>>
Lesson 2 Gradient Desent
查看>>
find border vertex
查看>>
matlab sliced variable
查看>>
create symbolic array
查看>>
TAUCS库的编译(vs2010)
查看>>
color vector using in plotting example points and lines between corresponding vertices
查看>>
mex 里面调用matlab函数
查看>>
matlab中cuda编程中分配grid和block dimension的时候的注意事项
查看>>
GPU CUDA and MEX Programming
查看>>
arrayfun用法
查看>>
矩阵积分
查看>>
optimization on macOS
查看>>
Template-Based 3D Model Fitting Using Dual-Domain Relaxation
查看>>
install libfreenect2 on ubuntu 16.04
查看>>
how to use automake to build files
查看>>
using matlab drawing line graph for latex
查看>>
How package finding works
查看>>