阅读 297

ElasticSearch不支持分组查询么?

在使用es进行组合查询的时候,遇到一个非常有意思的场景,特此记录一下

某些场景下,直接针对某个Field进行分组查询,居然无法返回结果,会给出类似Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default的提示信息,接下来看一下这个问题是个什么情况,以及如何解决

1. 数据准备

初始化一个索引,写入一些测试数据

post second-index/_doc {   "url": "/test",   "execute": {     "args": "id=10&age=20",     "cost": 10,     "res": "test result"   },   "response_code": 200,   "app": "yhh_demo" } post second-index/_doc {   "url": "/test",   "execute": {     "args": "id=20&age=20",     "cost": 11,     "res": "test result2"   },   "response_code": 200,   "app": "yhh_demo" } post second-index/_doc {   "url": "/test",   "execute": {     "args": "id=10&age=20",     "cost": 12,     "res": "test result2"   },   "response_code": 200,   "app": "yhh_demo" } post second-index/_doc {   "url": "/hello",   "execute": {     "args": "tip=welcome",     "cost": 2,     "res": "welcome"   },   "response_code": 200,   "app": "yhh_demo" } post second-index/_doc {   "url": "/404",   "execute": {     "args": "tip=welcome",     "cost": 2,     "res": "xxxxxxxx"   },   "response_code": 404,   "app": "yhh_demo" } 复制代码

2. 分组查询基本知识点

相当于sql中的group by,常用于聚合操作中的统计计数的场景

在es中,使用aggs来实现,语法如下

"aggs": {     "agg-name": { // 这个agg-name 是自定义的聚合名称         "terms": { // 这个terms表示聚合的策略,根据 field进行分组             "field": "",             "size": 10         }     } } 复制代码

比如我们希望根据url统计访问计数,对应的查询可以是

GET second-index/_search {   "query": {     "match_all": {}   },   "size": 1,    "aggs": {     "my-agg": {       "terms": {         "field": "url",         "size": 2       }     }   } } 复制代码

直接执行上面的分组查询,结果问题来了

00.jpg

右边返回的提示信息为Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [url] in order to load field data by uninverting the inverted index. Note that this can use significant memory这个异常

3. 解决方案

简单来说,上面这个问题,就是因为url这个字段为text类型,默认情况下这种类型的不走索引,不支持聚合排序,如果需要则需要设置fielddata=true,或者使用url的分词url.keyword

GET second-index/_search {   "query": {     "match_all": {}   },   "size": 1,    "aggs": {     "my-agg": {       "terms": {         "field": "url.keyword",         "size": 2       }     }   } } 复制代码

01.jpg

注意

  • 虽然我们更注重的是分组后的结果,但是hits中依然会返回命中的文档,若是只想要分组后的统计结果,可以在查询条件中添加 size:0

  • 聚合操作和查询条件是可以组合的,如只查询某个url对应的计数

GET second-index/_search {   "query": {     "term": {       "url.keyword": {         "value": "/test"       }     }   },   "size": 1,    "aggs": {     "my-agg": {       "terms": {         "field": "url.keyword",         "size": 2       }     }   } } 复制代码

02.jpg

上面介绍了TEXT类型的field,根据分词进行聚合操作;还有一种方式就是设置fielddata=true,操作姿势如下

PUT second-index/_mapping {   "properties": {     "url": {       "type": "text",       "fielddata": true     }   } } 复制代码

修改完毕之后,再根据url进行分组查询,就不会抛异常了

03.jpg

4. 小结

最后小结一下,当我们使用es的某个field进行分组操作时,此时需要注意

当这个field类型为text,默认的场景下是不支持分组操作的,如果非要用它进行分组查询,有两个办法

  • 使用它的索引字段,如 url.keyword

  • 在索引的filed上添加fileddata: true 配置


作者:一灰灰
链接:https://juejin.cn/post/7033710453310095367


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐