由于项目需要,我们要使用Golang对ElasticSearch集群进行读写,当前在用的ES集群版本为6.4.3,使用的Golang版本的SDK库是https://github.com/olivere/elastic,但是在使用过程中发现按照官方版本提供的接口对数据进行检索时,会出现各种问题,整个排查过程也花费了几个小时,因此在这里记录下。
对于ES的Golang版本的SDK选择,相信大多数Go语言开发者都会比较熟悉https://github.com/olivere/elastic了,一方面因为ES官方在早期版本没有提供Golang版本的SDK,另外一方面是因为olivere写的库文档较全,并且国内有很多项目都在使用,同时在老东家的时候也是使用v2版本的库进行数据处理的。因此,虽然ES官方在几个月前发布了Goalng版本SDK: https://github.com/elastic/go-elasticsearch,但由于仅支持ES6和ES7版本,且使用案例较少,在使用过程中选择使用elastic 来实现需求。
我们都知道,Elasticsearch在版本上迭代也算比较快,因此在elastic库在支持的使用也分别通过版本声明的方式来对应固定的Elasticsearch的版本,但是从elastic的官方文档中看到,前四个版本都托管在了https://gopkg.in上,并且有固定的版本后缀,而到了ES6.X版本,开始托管在了https://github.com上,并且该版本没有显式声明版本。
在项目开始的时候,就直接使用github上托管的版本进行数据处理,写入没有任何异常,一切ok。
使用https://github.com/olivere/elastic 版本在数据全部写入之后,我打算对一些数据进行检索,快速将代码构造好之后,测试却发现如下异常:

我开始对核心代码逻辑逐个检查,并且尝试将ES查询部分逻辑独立出来进行测试,但是异常依旧。接下来,我打算继续重新查看sdk的官方示例,并进行debug.
官方文档:https://olivere.github.io/elastic/ 中提供了一段基本的ES6的示例代码,大概如下。

实现了基本的数据索引,检索以及索引更新和删除。但是,当我将示例代码拷贝到本地执行后依然异常。

第一个问题是提示searchResult.Hits.TotalHits 操作无效,查看官方v6的文档才发现,TotalHits这个对象已经变化了。
https://godoc.org/github.com/olivere/elastic#TotalHits


而在之前版本的结构是这样的:

新版本返回的是一个名为TotalHits结构体的指针,而老版本直接返回int64类型。
其实,想要获取查询命中个数,其实SearchResult还有一个method可用,文档中描述如下:

因此,想要解决异常的第一个问题,可以直接修改官方示例代码中的如下代码:
# 将
if searchResult.Hits.TotalHits > 0 {
# 修改为(建议直接使用结构体方法,因为方法是版本兼容的,而结构体通常会随版本的变化而变化)
if searchResult.TotalHits() > 0
# 或者
if searchResult.Hits.TotalHits.Value > 0

那我们可以尝试先不解析Source里的业务数据,可以将索引的一条数据完整的打印出来,因此可以将json序列化部分注释掉,核心代码如下:

再次运行发下如下异常:

panic触发的代码为构建查询时捕获到的错误:

但是构造的这个查询结构实在看不出有什么异常,所以猜想的可能是sdk兼容问题,后来在github的issiue中看到有人有同样的问题. 所以,直接的解决方案就是使用声明式的版本来指定estic.v6版本来使用。
即:

接下来运行就会比较嗨了。

这里红框里的内容就是打印到检索命中的内容,接下来,我们将hit.Source解析出来(取消上面的注释内容)。

红框里就是我们要解析的hit.Source中的内容。
至此,使用elastic.v6来处理ES中的数据再无相关异常。
关于版本:在使用Golang开发程序时,非常推荐强声明版本信息(当然其他语言也非常建议这么做)
关于使用:通常在推荐使用结构体方法来操作对象,因为结构体通常会随着版本的变化而变化数据结构,会导致兼容性问题。
关于开源:开源软件的好处就是源代码可以自由浏览,从文档中找不到的可以直接查看源码进行debug,因此开源软件的使用还是需要能够看懂,能及时debug来解决自己的问题
关于文档:不确定是否是作者v6版文档的问题,但是我遇到这些问题了,所以说文档永远只是参考工具,绝知此事要躬行啊。
原文作者:云原生运维技术;如有侵权,请联系管理员删除。