【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(五)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(五)

聚合查询

聚合查询实际上是一种统计和计算,按照官方文档的解释共有四类

  • Metric(指标): 指标分析类型,如计算最大值、最小值、平均值等等 (对桶内的文档进行聚合分析的操作)
  • Bucket(桶): 分桶类型,类似SQL中的GROUP BY语法 (满足特定条件的文档的集合)
  • Pipeline(管道): 管道分析类型,基于上一级的聚合分析结果进行在分析
  • Matrix(矩阵): 矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)

一般聚合的写法如下:

"aggregations" : {
    "<aggregation_name>" : {                                 <!--聚合的名字 -->
        "<aggregation_type>" : {                               <!--聚合的类型 -->
            <aggregation_body>                                 <!--聚合体:对哪些字段进行聚合 -->
        }
        [,"meta" : {  [<meta_data_body>] } ]?               <!--元 -->
        [,"aggregations" : { [<sub_aggregation>]+ } ]?   <!--在聚合里面在定义子聚合 -->
    }
    [,"<aggregation_name_2>" : { ... } ]*                     <!--聚合的名字 -->
}

其中aggregations 也可简写为 aggs,虽然Elasticsearch有四种聚合方式,但在一般实际开发中,用到的比较多的就是Metric和Bucket。其实从功能上只有前两类:一类是进行数学计算聚合使用的【max、min、avg、sum、stats 】,类似sql里的函数,也就是ES里的统计聚合,另一类则是进行分组聚合使用的,类似sql里的group,也就是ES里的桶聚合。剩余的两类就是程序上的辅助聚合方式,一种是管道二次处理,一种似是分桶同时处理统计计算

桶(bucket)

  • 简单来说桶就是满足特定条件的文档的集合。*
  • 当聚合开始被执行,每个文档里面的值通过计算来决定符合哪个桶的条件,如果匹配到,文档将放入相应的桶并接着开始聚合操作。
  • 桶也可以被嵌套在其他桶里面。

指标(metric)

  • 桶能让我们划分文档到有意义的集合,但是最终我们需要的是对这些桶内的文档进行一些指标的计算。分桶是一种达到目的地的手段:它提供了一种给文档分组的方法来让我们可以计算感兴趣的指标。
  • 大多数指标是简单的数学运算(如:最小值、平均值、最大值、汇总),这些是通过文档的值来计算的。

接下来我们分别实践一下。

桶聚合

我们先来看一个桶聚合,例如我们想要进行如下聚合【按照年龄聚合,0-10,10-20,20-30】,查询语句如下:

{
  "size": 0, 
  "aggs": {
    "user_age_info": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 0,
            "to": 10
          },
          {
            "from": 11,
            "to": 20
          },
          {
            "from": 21,
            "to": 30
          }
        ]
      }
    }
  }
}

返回结果为:

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "user_age_info": {
            "buckets": [
                {
                    "key": "0.0-10.0",
                    "from": 0.0,
                    "to": 10.0,
                    "doc_count": 4
                },
                {
                    "key": "11.0-20.0",
                    "from": 11.0,
                    "to": 20.0,
                    "doc_count": 7
                },
                {
                    "key": "21.0-30.0",
                    "from": 21.0,
                    "to": 30.0,
                    "doc_count": 4
                }
            ]
        }
    }
}

指标聚合

指标聚合分为两种,分别是单值分析和多值分析,各自有几个查询关键字:

  • 单值分析只输出一个分析结果:min,max,avg,sum,cardinality
  • 多值分析输出多个分析结果:stats, extended_stats, percentile, percentile_rank, top hits
    统计计算这里我们分别使用一下以上几种方式进行分析,最后再结合分组进行一些复合的统计计算查询。

单值分析

我们分别带入场景来进行单值指标的聚合分析。

max

这里我们想查询,所有员工信息中,【年龄最大的员工】,则查询参数为:

{
    "size":0,
    "aggs" : {
        "max_age" : { "max" : { "field" : "age" } }
    }
}

返回为:

{
    "took": 15,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "max_age": {
            "value": 28.0
        }
    }
}

min

这里我们想查询,所有员工信息中,【年龄最小的员工】,则查询参数为:

{
    "size":0,
    "aggs" : {
        "min_age" : { "min" : { "field" : "age" } }
    }
}

返回结果为:

{
    "took": 6,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "min_age": {
            "value": 8.0
        }
    }
}

avg

这里我们想查询,所有员工信息中,【平均年龄是多少】,则查询参数为:

{
    "size":0,
    "aggs" : {
        "avg_age" : { "avg" : { "field" : "age" } }
    }
}

返回结果为:

{
    "took": 19,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "avg_age": {
            "value": 18.0
        }
    }
}

sum

这里我们想查询,所有员工信息中,【年龄总和为多大】,则查询参数为:

{
    "size":0,
    "aggs" : {
        "sun_age" : { "sum" : { "field" : "age" } }
    }
}

返回结果为:

{
    "took": 9,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sun_age": {
            "value": 270.0
        }
    }
}

cardinality

cardinality 求唯一值,即不重复的字段有多少(相当于mysql中的distinct),我们现在查询所有员工信息共有多少种年龄,请求参数为:

{
    "size":0,
    "aggs" : {
        "age_count" : { "cardinality" : { "field" : "age" } }
    }
}

返回值为:

{
    "took": 22,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sex_count": {
            "value": 3
        }
    }
}

共有8、18、28三种年龄

多值分析

多值分析包括以下关键字stats,extended_stats,percentile,percentile_rank,top hits,我们一个一个讨论下

stats

我想统计所有员工年龄的各种单值分析状态,可以使用stats,请求参数如下:

{
    "size":0,
    "aggs" : {
        "age_stats" : { "stats" : { "field" : "age" } }
    }
}

返回值为:

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "age_stats": {
            "count": 15,
            "min": 8.0,
            "max": 28.0,
            "avg": 18.0,
            "sum": 270.0
        }
    }
}

Percentiles

对指定字段的值按从小到大累计每个值对应的文档数的占比,返回指定占比比例对应的值。默认按照[ 1, 5, 25, 50, 75, 95, 99 ]来统计,我们想统计各个年龄百分区间内员工的数量:

{
    "size":0,
    "aggs" : {
        "age_percentiles" : { "percentiles" : { "field" : "age" } }
    }
}

返回结果为:

{
    "took": 15,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "age_percentiles": {
            "values": {
                "1.0": 8.0,
                "5.0": 8.0,
                "25.0": 10.5,
                "50.0": 18.0,
                "75.0": 25.5,
                "95.0": 28.0,
                "99.0": 28.0
            }
        }
    }
}

可以理解为99%的员工都小于等于28岁。这个按百分值进行强制分布

Percentile Ranks

上面是通过百分比求文档值,这里通过文档值求百分比,请求参数为:

{
    "size":0,
    "aggs" : {
        "age_percentile_ranks" : { "percentile_ranks" : { "field" : "age","values" : [8, 18,28] } }
    }
}

返回值为:

{
    "took": 11,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "age_percentile_ranks": {
            "values": {
                "8.0": 20.0,
                "18.0": 66.66666666666666,
                "28.0": 100.0
            }
        }
    }
}

age<=8岁的占比20%,感觉两种百分比的形式还是不是非常准确的,关于查询的准确性我们之后再另行讨论。

分桶指标复合分析

这里我们来依据年龄段进行,分析,想要进行如下聚合【按照年龄聚合,0-20,20-40】,并且对每个年龄段内的年龄进行平均值计算。

{
  "size": 0, 
  "aggs": {
    "user_age_info": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 0,
            "to": 20
          },
          {
            "from": 21,
            "to": 40
          }
        ]
      },
       "aggs": {
            "age_avg": {
              "avg": {
                "field": "age"
              }
            }
          }
    }
  }
}

返回值为:

{
    "took": 7,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 15,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "user_age_info": {
            "buckets": [
                {
                    "key": "0.0-20.0",
                    "from": 0.0,
                    "to": 20.0,
                    "doc_count": 11,
                    "age_avg": {
                        "value": 14.363636363636363
                    }
                },
                {
                    "key": "21.0-40.0",
                    "from": 21.0,
                    "to": 40.0,
                    "doc_count": 4,
                    "age_avg": {
                        "value": 28.0
                    }
                }
            ]
        }
    }
}

0到20岁之间共4个8岁,7个11岁,平均值为14.36岁。总而言之,桶聚合一般关键字为keyword,用来分类。

总结

以上就是周一到周四,四天的早上起大早的成果,将近3万字的成果,分别为普通模式、复合模式以及聚合模式,当然更复杂的将这几种融合起来的查询方式也是有的,等待后续的探索和学习啦。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
存储 固态存储 Java
Elasticsearch中查询性能优化
Elasticsearch中查询性能优化
196 0
|
3月前
|
安全 Linux 开发工具
Elasticsearch 搜索入门技术之一
Elasticsearch 搜索入门技术之一
227 1
|
2月前
|
存储 关系型数据库 MySQL
ElasticSearch 入门
【2月更文挑战第7天】ElasticSearch 入门 简介 ElasticSearch 的基本概念 ElasticSearch 的查询流程 ElasticSearch 的更新流程
37 2
|
2月前
|
缓存 算法 索引
【Elasticsearch专栏 07】深入探索:Elasticsearch的倒排索引如何进行模糊查询和通配符查询
Elasticsearch的倒排索引支持模糊查询和通配符查询,通过特定的算法和数据结构,能够实现对关键词的模糊匹配和通配符匹配。这两种查询类型提供了更灵活的搜索功能,但可能影响查询性能,需结合优化策略使用。
|
2月前
|
存储 自然语言处理 搜索推荐
ElasticSearch入门篇
ElasticSearch入门篇
|
2月前
|
存储 JSON 测试技术
异步检索在 Elasticsearch 中的理论与实践
异步检索在 Elasticsearch 中的理论与实践
36 0
|
2月前
|
缓存 自然语言处理 数据挖掘
一篇文章让你学会Elasticsearch中的查询
一篇文章让你学会Elasticsearch中的查询
137316 118
|
2月前
|
测试技术 定位技术 API
万字长文:一文彻底搞懂Elasticsearch中Geo数据类型查询、聚合、排序
万字长文:一文彻底搞懂Elasticsearch中Geo数据类型查询、聚合、排序
94615 140
|
2月前
|
JSON 前端开发 API
【Elasticsearch】搜索结果处理和RestClient查询文档
【Elasticsearch】搜索结果处理和RestClient查询文档
339 0
|
2月前
|
JSON 自然语言处理 算法
【Elasticsearch】DSL查询文档
【Elasticsearch】DSL查询文档
317 0

热门文章

最新文章