211123-ElasticSearch分组查询抛异常?

文章目录
  1. 1. 数据准备
  2. 2. 分组查询基本知识点
  3. 3. 解决方案
  4. 4. 小结
  • 一灰灰的联系方式
  • 在使用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. 数据准备

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    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来实现,语法如下

    1
    2
    3
    4
    5
    6
    7
    8
    "aggs": {
    "agg-name": { // 这个agg-name 是自定义的聚合名称
    "terms": { // 这个terms表示聚合的策略,根据 field进行分组
    "field": "",
    "size": 10
    }
    }
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    GET second-index/_search
    {
    "query": {
    "match_all": {}
    },
    "size": 1,
    "aggs": {
    "my-agg": {
    "terms": {
    "field": "url",
    "size": 2
    }
    }
    }
    }

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

    右边返回的提示信息为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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    GET second-index/_search
    {
    "query": {
    "match_all": {}
    },
    "size": 1,
    "aggs": {
    "my-agg": {
    "terms": {
    "field": "url.keyword",
    "size": 2
    }
    }
    }
    }

    注意

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    GET second-index/_search
    {
    "query": {
    "term": {
    "url.keyword": {
    "value": "/test"
    }
    }
    },
    "size": 1,
    "aggs": {
    "my-agg": {
    "terms": {
    "field": "url.keyword",
    "size": 2
    }
    }
    }
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    PUT second-index/_mapping
    {
    "properties": {
    "url": {
    "type": "text",
    "fielddata": true
    }
    }
    }

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

    4. 小结

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

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

    • 使用它的索引字段,如 url.keyword
    • 在索引的filed上添加fileddata: true 配置

    一灰灰的联系方式

    尽信书则不如无书,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    QrCode

    评论

    Your browser is out-of-date!

    Update your browser to view this website correctly. Update my browser now

    ×