elasticsearch聚合查询实践

这篇具有很好参考价值的文章主要介绍了elasticsearch聚合查询实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 概念
    • 聚合分类
    • 聚合语法
    • 聚合作用范围及排序
    • 聚合原理及 terms 精准度
  • 聚合实验
    • 桶聚合
    • 指标聚合
    • Pipeline 聚合
  • 实践一:多商户数据权限聚合分页
  • 实践二:多维度嵌套聚合
  • 实践三:删除 ES 索引重复数据
  • 附:实验环境

概念

用于聚合的字段必须是 exact value,即doc_value=true。分词字段不可进行聚合,对于 text 字段如需使用聚合,需开启 fielddata,不推荐因容易造成 OOM。

聚合分类

  1. Bucket aggregations(桶聚合)

  2. Metric aggregations(指标聚合)

  3. Pipeline aggregations(管道聚合)

聚合语法

request

GET /my-index/_search
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

response

{
  "took": 78,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [...]
  },
  "aggregations": {
    "my-agg-name": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": []
    }
  }
}

聚合作用范围及排序

  • queryfilter,是先选定数据范围,再聚合桶;

  • post_filter 对聚合桶没影响,桶全部返回,只对查询结果进行过滤返回,功能类似 mysql 中的 having;

  • global 的作用是覆盖掉 query 的查询作用。

聚合原理及 terms 精准度

Terms Aggregation 的返回中有两个特殊的数值

  • doc_count_error_upper_bound:被遗漏的 term 分桶,包含的文档,有可能的最大值

  • sum_other_doc_count:除了返回结果 bucket 的 terms 以外,其他的 terms 的文档总数(总数-返回的总数)

聚合实验

实验数据引用自《Elasticsearch 核心技术与实战》- 阮一鸣(eBay Pronto 平台技术负责人)

创建索引

PUT /employees/
{
  "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "gender" : {
          "type" : "keyword"
        },
        "job" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 50
            }
          }
        },
        "name" : {
          "type" : "keyword"
        },
        "salary" : {
          "type" : "integer"
        }
      }
    }
}

批量写入数据

PUT /employees/_bulk
{ "index" : {  "_id" : "1" } }
{ "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }
{ "index" : {  "_id" : "2" } }
{ "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}
{ "index" : {  "_id" : "3" } }
{ "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }
{ "index" : {  "_id" : "4" } }
{ "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}
{ "index" : {  "_id" : "5" } }
{ "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }
{ "index" : {  "_id" : "6" } }
{ "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}
{ "index" : {  "_id" : "7" } }
{ "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }
{ "index" : {  "_id" : "8" } }
{ "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}
{ "index" : {  "_id" : "9" } }
{ "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }
{ "index" : {  "_id" : "10" } }
{ "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}
{ "index" : {  "_id" : "11" } }
{ "name" : "Jenny","age":36,"job":"Java Programmer","gender":"female","salary":38000 }
{ "index" : {  "_id" : "12" } }
{ "name" : "Mcdonald","age":31,"job":"Java Programmer","gender":"male","salary": 32000}
{ "index" : {  "_id" : "13" } }
{ "name" : "Jonthna","age":30,"job":"Java Programmer","gender":"female","salary":30000 }
{ "index" : {  "_id" : "14" } }
{ "name" : "Marshall","age":32,"job":"Javascript Programmer","gender":"male","salary": 25000}
{ "index" : {  "_id" : "15" } }
{ "name" : "King","age":33,"job":"Java Programmer","gender":"male","salary":28000 }
{ "index" : {  "_id" : "16" } }
{ "name" : "Mccarthy","age":21,"job":"Javascript Programmer","gender":"male","salary": 16000}
{ "index" : {  "_id" : "17" } }
{ "name" : "Goodwin","age":25,"job":"Javascript Programmer","gender":"male","salary": 16000}
{ "index" : {  "_id" : "18" } }
{ "name" : "Catherine","age":29,"job":"Javascript Programmer","gender":"female","salary": 20000}
{ "index" : {  "_id" : "19" } }
{ "name" : "Boone","age":30,"job":"DBA","gender":"male","salary": 30000}
{ "index" : {  "_id" : "20" } }
{ "name" : "Kathy","age":29,"job":"DBA","gender":"female","salary": 20000}

桶聚合

对 keword 进行聚合

GET employees/_search
{
  "size": 0,
  "aggs": {
    "jobs": {
      "terms": {
        "field":"job.keyword"
      }
    }
  }
}

指标聚合

多个 Metric 聚合,找到最低最高和平均 salary

GET employees/_search
{
  "size": 0,
  "aggs": {
    "max_salary": {
      "max": {
        "field": "salary"
      }
    },
    "min_salary": {
      "min": {
        "field": "salary"
      }
    },
    "avg_salary": {
      "avg": {
        "field": "salary"
      }
    }
  }
}

多次嵌套,根据工作类型分桶,然后按照性别分桶,计算 salary 的统计信息

GET employees/_search
{
  "size": 0,
  "aggs": {
    "job_gender_stats": {
      "terms": {
        "field": "job.keyword"
      },
      "aggs": {
        "gender_stats": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "salary_stats": {
              "stats": {
                "field": "salary"
              }
            }
          }
        }
      }
    }
  }
}

response

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 20,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "job_gender_stats" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Java Programmer",
          "doc_count" : 7,
          "gender_stats" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "male",
                "doc_count" : 5,
                "salary_stats" : {
                  "count" : 5,
                  "min" : 9000.0,
                  "max" : 32000.0,
                  "avg" : 22200.0,
                  "sum" : 111000.0
                }
              },
              {
                "key" : "female",
                "doc_count" : 2,
                "salary_stats" : {
                  "count" : 2,
                  "min" : 30000.0,
                  "max" : 38000.0,
                  "avg" : 34000.0,
                  "sum" : 68000.0
                }
              }
            ]
          }
        },
        ......
      ]
    }
  }
}

Pipeline 聚合

平均 salary 的统计分析

GET employees/_search
{
  "size": 0,
  "aggs": {
    "jobs": {
      "terms": {
        "field": "job.keyword",
        "size": 10
      },
      "aggs": {
        "avg_salary": {
          "avg": {
            "field": "salary"
          }
        }
      }
    },
    "stats_salary_by_job":{
      "stats_bucket": {
        "buckets_path": "jobs>avg_salary"
      }
    }
  }
}

实践一:多商户数据权限聚合分页

collapse + cardinality 实现分页去重查询

GET my_order/_search
{
  "from": 0,
  "size": 6,
  "track_total_hits": true,
  "query": {
    "bool": {
      "must": [
        {
          "terms": {
            "tenant_id": [
              1,
              2,
              3,
              4
            ]
          }
        }
      ]
    }
  },
  "aggs": {
    "cidAgg": {
      "cardinality": {
        "field": "cid"
      }
    }
  },
  "collapse": {
    "field": "cid"
  }
}

注:不支持 search_after,导出推荐 scroll

实践二:多维度嵌套聚合

date_histogram 日期直方图 + terms 分桶聚合过去一周每天产生的工单量,每天各品类工单量,每天各品类排名前 N 的爆品等等。

GET my_order/_search
{
  "size": 0,
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "created_at": {
              "gte": "2023-11-10",
              "lte": "2023-11-16"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "ranges": {
      "date_histogram": {
        "field": "created_at",
        "format": "yyyy-MM-dd",
        "calendar_interval": "day"
      },
      "aggs": {
        "order_type_agg": {
          "terms": {
            "field": "order_type"
          }
        }
      }
    }
  }
}

实践三:删除 ES 索引重复数据

核酸检测数据量大,数据存储选型如使用 elasticsearchclick house 等列数据库,数据重复是绕不开的话题,应用可通过计划任务等方式检测到重复数据并及时处理。

单字段查重

GET my_order/_search
{
  "size": 0,
  "query": {
    "term": {
      "tenant_id": 1
    }
  },
  "aggs": {
    "duplicateCount": {
      "terms": {
        "field": "cid",
        "size": 1000,
        "min_doc_count": 2
      }
    }
  }
}

多字段查重

GET my_order/_search
{
  "size": 0,
  "aggs": {
    "duplicateCount": {
      "terms": {
        "script": {
          "lang": "painless",
          "source": "doc['tenant_id'].value + doc['cid'].value"
        },
        "size": 100,
        "min_doc_count": 2
      }
    }
  }
}

数据查重并在 duplicateDocuments 数组展示细节

GET my_order/_search
{
  "size": 0,
  "aggs": {
    "duplicateCount": {
      "terms": {
        "script": {
          "lang": "painless",
          "source": "doc['tenant_id'].value + doc['cid'].value"
        },
        "size": 100,
        "min_doc_count": 2
      },
      "aggs": {
        "duplicateDocuments": {
          "top_hits": {}
        }
      }
    }
  }
}

查询到的重复数据记入日志,核实后使用_delete_by_query删除

POST my_order/_delete_by_query?conflicts=proceed&max_docs=1
{
  "query": {
    "term": {
      "cid": 2
    }
  }
}

max_docs为 response 当前 key 中bucket.doc_count的数量-1

php版本 demo 供参考

public function clearDuplicate()
{
    $index = 'my_order';
    $client = ClientBuilder::create()->build();
    $params = [
        'index' => $index,
        'size' => 0,
        'body' => [
            'query' => [
                ...
            ],
            'aggs' => [
                'duplicateCount' => [
                    'terms' => [
                        'field' => 'cid',
                        'size' => 1000,
                        'min_doc_count' => 2
                    ]
                ]
            ],
        ],
    ];
    $result = $client->search($params);
    $bucket = ArrayHelper::getValue($result, 'aggregations.duplicateCount.buckets');
    if (!is_array($bucket) || empty($bucket)) {
        return;
    }
    foreach ($bucket as $item) {
        $maxDocs = ArrayHelper::getValue($item, 'doc_count', 0) - 1;
        $key = ArrayHelper::getValue($item, 'key');
        if ($maxDocs < 1 || empty($key)) {
            continue;
        }
        $client->deleteByQuery([
            'index' => $index,
            'conflicts' => 'proceed',
            'max_docs' => $maxDocs,
            'body' => [
                'query' => [
                    'bool' => [
                        ...
                    ],
                ],
            ],
        ]);
    }
}

附:实验环境

linux 操作系统

$ uname -a
Linux LAPTOP-QK4HAU1D 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/issue
Ubuntu 22.04.2 LTS \n \l

elasticsearch 版本

GET /
{
  "name" : "elasticsearch",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "6xwN3rfbQ2KGgQdt8IUKqg",
  "version" : {
    "number" : "7.16.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "2b937c44140b6559905130a8650c64dbd0879cfb",
    "build_date" : "2021-12-18T19:42:46.604893745Z",
    "build_snapshot" : false,
    "lucene_version" : "8.10.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
elasticsearch聚合查询实践,elasticsearch,elasticsearch,php
扫码关注微信公众号

参考:
[1] https://gitee.com/geektime-geekbang/geektime-ELK
[2] https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-aggregations.html文章来源地址https://www.toymoban.com/news/detail-770076.html

到了这里,关于elasticsearch聚合查询实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一起学Elasticsearch系列-聚合查询

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 聚合查询是 Elasticsearch 中一种强大的数据分析工具,用于从索引中提取和计算有关数据的统计信息。聚合查询可以执行各种聚合操作,如计数、求和、平均值、最小值、最大值、分组等,以便进行数据汇总和

    2024年01月22日
    浏览(38)
  • Elasticsearch 聚合查询(Aggregation)详解

    Elasticsearch中的聚合查询,类似SQL的SUM/AVG/COUNT/GROUP BY分组查询,主要用于统计分析场景。 实例: 例子聚合统计的效果等价SQL:

    2024年02月04日
    浏览(33)
  • elasticsearch中的聚合分组查询

    分组聚合及嵌套查询 聚合查询可以理解为SQL中的求和、求最大值、最小值以及求均值的需求 嵌套可以理解为es存值的某一个字段为对象属性的值做处理. Elasticsearch Java API分组与聚合结合 其中对字段field_one进行分组,分组的别名为fieldOne,取2^31-1组数据.如果不设置size,查询的结果

    2024年02月11日
    浏览(37)
  • Elasticsearch 基本使用(四)聚合查询

    说到聚合查询,马上会想到 SQL 中的 group by,ES中也有类似的功能,名叫 Aggregation。 统计分组后的数量 按年龄分组,然后统计每个年龄人数 count(*) ,age xxx group by age 非文档字段分组 文档字段分组 直接使用文档字段分组会报错。 ES没有对文本字段聚合,排序等操作优化;如果对

    2024年02月12日
    浏览(38)
  • Elasticsearch 查询和聚合查询:基本语法和统计数量

    摘要:Elasticsearch是一个强大的分布式搜索和分析引擎,提供了丰富的查询和聚合功能。本文将介绍Elasticsearch的基本查询语法,包括预发查询和聚合查询,以及如何使用聚合功能统计数量。 Elasticsearch是一种开源的分布式搜索和分析引擎,广泛应用于各种场景,包括日志分析、

    2024年02月11日
    浏览(36)
  • ElasticSearch(7.8版本)聚合查询使用javaHighLevelRestClient实现(从MySQL聚合查询概念->ES聚合概念及实操)

    申明:本文是在实现ES聚合功能中,将过程中查找的多篇博客文献拼接在一起,参考到的博文全部在标题中附上了原文的超链接,分享出来仅是为了提做一个笔记以防忘记,并给大家提供一个参考。 聚合操作指的是在数据查找基础上对于数据进一步整理筛选行为,聚合操作也

    2023年04月24日
    浏览(44)
  • ElasticSearch java API - 聚合查询

    }, “low”: { “type”: “long” }, “date”: { “format”: “strict_date_optional_time||epoch_millis”, “type”: “date” }, “close”: { “type”: “long” } }, “_all”: { “enabled”: false } } } 索引中的全部数据: name age salary team position james 33 3000 cav sf irving 25 2000 cav pg curry 29 1000 war pg thompson 26

    2024年04月10日
    浏览(29)
  • ElasticSearch搜索技术深入与聚合查询实战

    分词器官方称之为文本分析器,顾名思义,是对文本进行分析处理的一种手段,基本处理逻辑为按照预先制定的分词规则,把原始文档分割成若干更小粒度的词项,粒度大小取决于分词器规则。 分词器的处理过程发生在 Index Time 和 Search Time 两个时期。 Index Time:文档写入并创

    2024年02月06日
    浏览(38)
  • Java Elasticsearch多条件分组聚合查询

    需求         在项目开发中,需要从elasticsearch中查询日志数据,先统计每一天的日志调用量,然后在每一天的分组聚合基础上,再分组聚合统计成功和失败的日志调用量。 代码

    2024年02月08日
    浏览(42)
  • 五、浅析[ElasticSearch]底层原理与分组聚合查询

    集群节点介绍 es配置文件夹中 客户端节点 当主节点和数据节点配置都设置为false的时候,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户节点表现为智能负载平衡器。独立的客户端节点在一个比较大的集群中是非常有用的,他协调主节点和数据节

    2024年02月16日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包