• Elasticsearch聚合 之 Terms


    本篇着重讲解的terms聚合,它是按照某个字段中的值来分类:

    比如性别有男、女,就会创建两个桶,分别存放男女的信息。默认会搜集doc_count的信息,即记录有多少男生,有多少女生,然后返回给客户端,这样就完成了一个terms得统计。

    Terms聚合

    {
        "aggs" : {
            "genders" : {
                "terms" : { "field" : "gender" }
            }
        }
    }

    得到的结果如下:

    {
        ...
    
        "aggregations" : {
            "genders" : {
                "doc_count_error_upper_bound": 0, 
                "sum_other_doc_count": 0, 
                "buckets" : [ 
                    {
                        "key" : "male",
                        "doc_count" : 10
                    },
                    {
                        "key" : "female",
                        "doc_count" : 10
                    },
                ]
            }
        }
    }

    数据的不确定性

    使用terms聚合,结果可能带有一定的偏差与错误性。

    举个例子:

    我们想要获取name字段中出现频率最高的前5个。

    此时,客户端向ES发送聚合请求,主节点接收到请求后,会向每个独立的分片发送该请求。
    分片独立的计算自己分片上的前5个name,然后返回。当所有的分片结果都返回后,在主节点进行结果的合并,再求出频率最高的前5个,返回给客户端。

    这样就会造成一定的误差,比如最后返回的前5个中,有一个叫A的,有50个文档;B有49。但是由于每个分片独立的保存信息,信息的分布也是不确定的。有可能第一个分片中B的信息有2个,但是没有排到前5,所以没有在最后合并的结果中出现。这就导致B的总数少计算了2,本来可能排到第一位,却排到了A的后面。

    size与shard_size

    为了改善上面的问题,就可以使用size和shard_size参数。

    • size参数规定了最后返回的term个数(默认是10个)
    • shard_size参数规定了每个分片上返回的个数
    • 如果shard_size小于size,那么分片也会按照size指定的个数计算

    通过这两个参数,如果我们想要返回前5个,size=5;shard_size可以设置大于5,这样每个分片返回的词条信息就会增多,相应的误差几率也会减小。

    order排序

    order指定了最后返回结果的排序方式,默认是按照doc_count排序。

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "field" : "gender",
                    "order" : { "_count" : "asc" }
                }
            }
        }
    }

    也可以按照字典方式排序:

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "field" : "gender",
                    "order" : { "_term" : "asc" }
                }
            }
        }
    }

    当然也可以通过order指定一个单值的metric聚合,来排序。

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "field" : "gender",
                    "order" : { "avg_height" : "desc" }
                },
                "aggs" : {
                    "avg_height" : { "avg" : { "field" : "height" } }
                }
            }
        }
    }

    同时也支持多值的Metric聚合,不过要指定使用的多值字段:

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "field" : "gender",
                    "order" : { "height_stats.avg" : "desc" }
                },
                "aggs" : {
                    "height_stats" : { "stats" : { "field" : "height" } }
                }
            }
        }
    }

    min_doc_count与shard_min_doc_count

    聚合的字段可能存在一些频率很低的词条,如果这些词条数目比例很大,那么就会造成很多不必要的计算。
    因此可以通过设置min_doc_count和shard_min_doc_count来规定最小的文档数目,只有满足这个参数要求的个数的词条才会被记录返回。

    通过名字就可以看出:

    • min_doc_count:规定了最终结果的筛选
    • shard_min_doc_count:规定了分片中计算返回时的筛选

    script

    桶聚合也支持脚本的使用:

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "script" : "doc['gender'].value"
                }
            }
        }
    }

    以及外部脚本文件:

    {
        "aggs" : {
            "genders" : {
                "terms" : {
                    "script" : {
                        "file": "my_script",
                        "params": {
                            "field": "gender"
                        }
                    }
                }
            }
        }
    }

    filter

    filter字段提供了过滤的功能,使用两种方式:include可以过滤出包含该值的文档;相反则使用exclude。
    例如:

    {
        "aggs" : {
            "tags" : {
                "terms" : {
                    "field" : "tags",
                    "include" : ".*sport.*",
                    "exclude" : "water_.*"
                }
            }
        }
    }

    上面的例子中,最后的结果应该包含sport并且不包含water。
    也支持数组的方式,定义包含与排除的信息:

    {
        "aggs" : {
            "JapaneseCars" : {
                 "terms" : {
                     "field" : "make",
                     "include" : ["mazda", "honda"]
                 }
             },
            "ActiveCarManufacturers" : {
                 "terms" : {
                     "field" : "make",
                     "exclude" : ["rover", "jensen"]
                 }
             }
        }
    }

    多字段聚合

    通常情况,terms聚合都是仅针对于一个字段的聚合。因为该聚合是需要把词条放入一个哈希表中,如果多个字段就会造成n^2的内存消耗。

    不过,对于多字段,ES也提供了下面两种方式:

    • 1 使用脚本合并字段
    • 2 使用copy_to方法,合并两个字段,创建出一个新的字段,对新字段执行单个字段的聚合。

    collect模式

    对于子聚合的计算,有两种方式:

    • depth_first 直接进行子聚合的计算
    • breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。

    默认情况下ES会使用深度优先,不过可以手动设置成广度优先,比如:

    {
        "aggs" : {
            "actors" : {
                 "terms" : {
                     "field" : "actors",
                     "size" : 10,
                     "collect_mode" : "breadth_first"
                 },
                "aggs" : {
                    "costars" : {
                         "terms" : {
                             "field" : "actors",
                             "size" : 5
                         }
                     }
                }
             }
        }
    }

    缺省值Missing value

    缺省值指定了缺省的字段的处理方式:

    {
        "aggs" : {
            "tags" : {
                 "terms" : {
                     "field" : "tags",
                     "missing": "N/A" 
                 }
             }
        }
    }
  • 相关阅读:
    c#使用selenium过滑动验证码
    C#构建数据类型不同的链表
    【疑难杂症】c#控制台应用程序卡输出
    只需三步,轻松体验office2019
    一文搞定C#.Net如何调用/交互Javascript
    逆向某微信小程序参数签名算法
    win10 IIS疑难杂症--处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    一台手机如何在微信语音/视频通话时把声音录下来
    android端日志查看调试利器Logcat Reader
    [开源]安卓调试神器-获取最上层Activity:TopActivity
  • 原文地址:https://www.cnblogs.com/ExMan/p/10548332.html
Copyright © 2020-2023  润新知