设为首页 加入收藏

TOP

ElasticSearch里面一些小坑笔记
2019-05-11 02:11:18 】 浏览:102
Tags:ElasticSearch 里面 些小 笔记
最近线上的es报了一个异常,核心信息如下:



No mapping found for [k1.k2.time] in order to sort on



我们的es索引是嵌套索引,上面的这个异常大致意思是说在某个shard里面嵌套结构里面
k1.k2.time这个字段不存在数据,所以排序失败。


我们知道在ES里面可以分shard和索引,大多数时候我们es索引都是自动按某个规则创建的,比如说按天,按月,按年,这个用过logstash的同学应该都比较熟悉,收集的log基本上都是按天生成索引的,然后我们用kibana查询或者自己写代码查询。


下面看一些问题场景:


(场景1)查询一个不存在的索引


默认情况下,查询一个不存在的索引是会报异常的(no such index....)
,那么如何避免这个问题呢?

有两种办法:

A:每次查询前去使用es的索引api判断这个索引存在不存在,如果不存在就不进行任何操作,存在的话在执行查询,这样就能避免,但这样的问题就是每次都得判断存在不存在多一次查询交互。


B:在构建查询时,使用通配符标识索引,如果这个索引不存在,查询结果就是空,但是不会报异常,这样比较方便,不需要关注存在不存在问题。

一个java api的例子如下:


SearchRequestBuilder search = client.prepareSearch("xxxxx2019-06-13*").setTypes("xxxx")


如上代码,查询这个不存在的索引,这段代码结果不会报错,推荐使用这种方法。


(场景2)查询一个不存在的字段


查询一个不存在的字段es是不会报错的


(场景3)排序一个不存在的字段

默认情况下,排序一个不存在的字段,在es里面也会报错。这里主要分三种情况:


A:排序的单个索引不存在这个字段

B:排序的单个索引存在这个字段,但是它分shard了,如果有3个shard,只有2个shard上有这个字段,另外一个shard上没有这个字段,那么它同样会报异常

C:跨索引查询,如果跨2个索引,一个索引上所有的shard都包含这个字段,另外一个索引有部分shard没有,那么也会出现这个问题

如何解决:

这个也比较好解决,在排序的时候,需要设置在maping里面不存在的里面,应该如何处理,容错代码如下:


search.addSort(SortBuilders.fieldSort("no_exists_field").unmappedType("integer").order(SortOrder.DESC))



注意unmappedType方法了,定义这个值不存在的时候,默认按什么类型处理。


(场景4)在一个不存在的字段上算count,max,min,sum,avg这些指标


求聚合统计这些指标时,也不会报错,但结果值列有不同,详情如下:

count:0
sum:0.0
max:-Infinity
min:Infinity
avg:NaN


(场景5)分组一个不存在的字段

分组一个不存在的字段,也不会报错,返回结果是空


上面这些场景基本涵盖了查询统计大多数的可能出现的问题,需要我们在使用的时候需要注意一下,避免一些不必要的问题。


最后我们来介绍一下es里面一个有用的查询Exists Query:

功能:查询的字段至少有一个非null值才回返回


我们来看官网给的一个例子:


{
"exists" : { "field" : "user" }
}


上面这个查询是查字段user的数据,是不是为空,注意下面的这些数据,是可以被匹配上


{ "user": "jane" } //有数据
{ "user": "" } //空串也代表有数据
{ "user": "-" } //符号也代表有数据
{ "user": ["jane"] }//数组也代表有数据
{ "user": ["jane", null ] } //数组里面有一个不是null也代表有数据



在来看下,那些情况,不能被匹配:


{ "user": null }//null值不能被匹配
{ "user": [] } //空数组不能被匹配
{ "user": [null] } //空数组包含null值也不能被匹配
{ "foo": "bar" } //user字段缺失,也不能被匹配




此外,Exists Query可以非常方便的替代Miss Query看下面的例子:

"bool": {
"must_not": {
"exists": {
"field": "user"
}
}
}


上面这个查询将返回没有user字段的数据,java api写法如下:

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.mustNot(QueryBuilders.existsQuery("user"));



注意,经过测试发现一个嵌套索引里面,如果只有一个为空的数组,然后使用嵌套查询Exists Query是会报错的,而使用平铺的Exists Query是不会报错的,也就是说,嵌套的索引里面必须有一个不为空的对象存在,才能使用Exists Query查询语法,来查询相关字段不存在的数据
否则会报错,这一点目前还没看到有任何好的办法来校验多级嵌套结构下的某个索引里面到底存不存在某个嵌套结构,嵌套索引的判断是否存在大致一样
唯一需要注意到是,嵌套结构,一定有一条不为空的数据存在才行

关于嵌套索引结构的校验,请参考下面这个链接:

[url]https://gist.github.com/Erni/7484095[/url]

[b][color=green][size=large]
有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。
技术债不能欠,健康债更不能欠, 求道之路,与君同行。
[/size][/color][/b]
[img]http://dl2.iteye.com/upload/attachment/0104/9948/3214000f-5633-3c17-a3d7-83ebda9aebff.jpg[/img]
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇UVA 11991 Easy Problem from Ruj.. 下一篇centos7.4 open-falcon 分机 监控..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目