当前位置:   article > 正文

【ElasticSearch笔记】ES基本查询_es 查询

es 查询

目录

一、简介

ES与关系型数据库对比

文本分析

倒排索引

二、基本查询

空查询

相关性

查询与过滤

1. 查询与"first blog"字段最佳匹配的文档

2. 搜索博客等级(level)大于等于2, 同时发布日期(post_date)是2018-11-11的博客

结构化搜索

1. 精确值查找(term)

2. 多个精确值查找(terms)

3. range(范围过滤)

4. 组合查询(bool)

5. 处理null值(exists)

全文搜索

1. match

2. bool(组合查询)

3. match_phrase(短语匹配)

分页(深度分页)from+size

排序

游标查询(scroll)

模糊查询

三、聚合分组

执行顺序及聚合写法

指标聚合(Metrics)

1. max、min、sum、avg

2. Value count

3. cardinality

4. stats

5.Extended stats

桶聚合(Buckets)

1. Terms Aggregation

2. Filter Aggregation

3. Filters Aggregation

4. Top_hits Aggregation

5. Date_histogram Aggregation


一、简介

Elasticsearch(ES):一款基于Apache Lucene(TM)的开源的全文检索和分析引擎。通过简单的RESTful API来隐藏其复杂性、同时也做了分布式相关的工作。

Lucene:使用Java实现的一套搜索引擎库。

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 分布式的实时分析搜索引擎
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

ES与关系型数据库对比

Elasticsearch集群可以包含多个索引(数据库),每一个索引可以包含多个类型(表),每一个类型包含多个文档(行),然后每个文档包含多个字段(列)

关系型数据库

数据库

ElasticSearch

索引(index)

类型(type)

文档

字段

相关概念:

  • 集群(cluster):一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。
  • 节点(node):一个节点就是集群中的一个服务器,作为集群的一部分,参与集群的索引和搜索功能。
  • 索引(index): 一个索引就是一个具有相似特征的文档集合,相当于一个数据集。
  • 类型(type):在一个索引中,你可以定义一种或多种类型,相当于对一个索引中数据的逻辑划分(ES官方文档明确说明不推荐使用type,即建议一个索引只有一个type。ES7.0已经废弃了type)。
  • 文档(document): 一个文档是一个可被索引的基础信息单元,就是索引里面的一条数据,使用JSON格式来表示。
  • 域(field): 文档中的一个数据字段。一个文档由多个域组成。
  • 分片(shards):分片是索引的一部分,一个索引由多个分片组成。每个分片可以分布在不同的节点上,ES会根据文档id(也可以指定其他字段)做hash,使用得到的hash值将文档路由到指定分片上。分片是ES做Data Rebalance的最小单元。
  • 副本(replicas):创建索引时可以为索引指定0个或者多个副本。副本是分片级别的,即索引的分片由1个主分片(primary shard)和0个或者多个副本分片(replica shard)组成。primary shard可以接受读取和写入请求,replica shard只能接受读取请求。所以副本只能提高数据的可用性和并发读取能力。当primary shard所在服务器的节点挂掉以后,ES会通过leader选举机制将replica shard为primary shard。

文本分析

将文本转换成一系列单词(Term or Token)的过程,用于创建和查询倒排索引

分词器:是ES中专门处理分词的组件,由一下三部分组成

  1. Character Filters:针对原始文本进行处理,比如去除html标签
  2. Tokenizer:将原始文本按照一定规则切分为单词
  3. Token Filters:针对Tokenizer处理的单词进行再加工,比如转小写、删除或增新等处理

内置分词器:

  1. Standard Analyzer:默认分词器,按词切分,小写处理,删除大多标点符号
  2. Simple Analyzer:按照非字母切分、小写处理
  3. Whitespace Analyzer:按照空白字符分割
  4. Keyword Analyzer:不分词

分词查看

  1. POST /_analyze
  2. {
  3. "analyzer": "standard",
  4. "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
  5. }

结果

  1. {
  2. "tokens": [{
  3. "token": "the",
  4. "start_offset": 0,
  5. "end_offset": 3,
  6. "type": "<ALPHANUM>",
  7. "position": 0
  8. },
  9. {
  10. "token": "2",
  11. "start_offset": 4,
  12. "end_offset": 5,
  13. "type": "<NUM>",
  14. "position": 1
  15. },
  16. ...
  17. ]
  18. }

详情点击跳转官方文档查看

倒排索引

ES把文档中的数据进行分析后,将词和文档之间建立映射关系。

组成:倒排索引由文档中不重复词的列表+每个词被包含的文档ID列表

查询过程:

  1. 搜索词“搜索引擎”,获得对应的文档ID列表,1,3
  2. 通过正排索引查询1和3的完整内容
  3. 返回最终结果

二、基本查询

空查询

  1. GET /_search
  2. {}
  3. GET /_search
  4. {
  5. "query": {
  6. "match_all": {}
  7. }
  8. }

字段详解

相关性

根据ES的相似度算法(TF/IDF)得出的结果,具体值由_score字段表示,根据以下维度计算得出

  • 检索词频率: 检索词在该字段出现的频率,频率越高,权重越大。字段中出现过 5 次要比只出现过 1 次的相关性高。
  • 反向文档频率:检索词在使用中出现的频率,频率越高,权重越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
  • 字段长度准则:字段长度越长,权重越低
  1. // 请求后增加explain=true即可
  2. GET /_search
  3. {
  4. "explain":true,
  5. "query" : { "match" : { "name" : "John Smith" }}
  6. }

查询与过滤

Query

Filter

争对问题

该文档匹不匹配这个查询,它的相关度高么❓

这篇文档是否与该查询匹配❓

相关度处理

先查询符合搜索条件的文档数,然后计算每个文档对于搜索条件的相关度分数,再根据评分倒序排序

只根据搜索条件过滤出符合的文档,   不进行评分, 忽略TF/IDF信息

性能

性能较差, 有排序 , 并且没有缓存功能(有倒排索引来弥补)

性能更好, 无排序;  会缓存比较常用的filter的数据

栗子

❗ 查询与“first blog”字段最佳匹配的文档 ❗

❗ 搜索博客等级(level)大于等于2, 同时发布日期(post_date)是2018-11-11的博客 ❗

1. 查询与"first blog"字段最佳匹配的文档

  1. // query
  2. GET /_search
  3. {
  4. "query": {
  5. "match": {
  6. "desc": "four blog"
  7. }
  8. }
  9. }
  10. // filter
  11. GET /_search
  12. {
  13. "query": {
  14. "bool": {
  15. "filter": {
  16. "match": {
  17. "desc": "four blog"
  18. }
  19. }
  20. }
  21. }
  22. }

2. 搜索博客等级(level)大于等于2, 同时发布日期(post_date)是2018-11-11的博客

  1. // query
  2. GET /_search
  3. {
  4. "query": {
  5. "bool": {
  6. "must": [
  7. { "match": { "post_date": "2018-11-11" } },
  8. { "range": { "level": { "gte": 2 } } }
  9. ]
  10. }
  11. }
  12. }
  13. // filter
  14. GET /_search
  15. {
  16. "query": {
  17. "bool": {
  18. "must": {
  19. "match": { "post_date": "2018-11-11" }
  20. },
  21. "filter": {
  22. "range": { "level": { "gte": 2 } }
  23. }
  24. }
  25. }
  26. }

结构化搜索

 插入测试数据

  1. POST /my_store/_bulk
  2. { "index": { "_id": 1 }}
  3. { "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
  4. { "index": { "_id": 2 }}
  5. { "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
  6. { "index": { "_id": 3 }}
  7. { "price" : 30, "productID" : "JODL-X-1937-#pV7" }
  8. { "index": { "_id": 4 }}
  9. { "price" : 30, "productID" : "QQPX-R-3956-#aD8" }

查看索引详情

GET /my_store

1. 精确值查找(term)

查询价格20的所有产品
SQL:SELECT * FROM products WHERE price = 20

  1. GET /_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "term" : {
  7. "price" : 20
  8. }
  9. }
  10. }
  11. }
  12. }
  13. // constant_score关键字将trem查询转化为filter
  14. GET /_search
  15. {
  16. "query":{
  17. "bool": {
  18. "filter": {
  19. "term": {
  20. "price": 20
  21. }
  22. }
  23. }
  24. }
  25. }

查询productID为XHDK-A-1293-#fJ3的文档

SQL:SELECT * FROM products WHERE  productID = "XHDK-A-1293-#fJ3"

  1. GET /_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "term" : {
  7. "productID" : "XHDK-A-1293-#fJ3"
  8. }
  9. }
  10. }
  11. }
  12. }
  13. // 查看分词结果
  14. GET /my_store/_analyze
  15. {
  16. "field": "productID",
  17. "text": "XHDK-A-1293-#fJ3"
  18. }

总结:term会拿"XHDK-A-1293-#fJ3",去倒排索引中找,但倒排索引表里只有"xhdk","a","1293","fj3",因此查不到


解决办法1

  1. GET /_search
  2. {
  3. "query" : {
  4. "match_phrase" : {
  5. "productID" : "XHDK-A-1293-#fJ3"
  6. }
  7. }
  8. }

解决办法2

  1. // 1.删除索引
  2. DELETE /my_store
  3. //2.指定productID字段使用keyword规则
  4. PUT /my_store
  5. {
  6. "mappings": {
  7. "properties": {
  8. "price": {
  9. "type": "long"
  10. },
  11. "productID": {
  12. "type": "text",
  13. "analyzer": "keyword"
  14. }
  15. }
  16. }
  17. }

2. 多个精确值查找(terms)

查找price为20 && 30 的文档

  1. GET /my_store/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "terms" : {
  7. "price" : [20, 30]
  8. }
  9. }
  10. }
  11. }
  12. }

3. range(范围过滤)

gt:>   lt:<    gte:>=  lte:<=

查找price大于20且小于40的产品
SQL:SELECT * FROM products WHERE  price BETWEEN 20 AND 40

  1. GET /my_store/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "range" : {
  7. "price" : {
  8. "gte" : 20,
  9. "lt" : 40
  10. }
  11. }
  12. }
  13. }
  14. }
  15. }

日期范围查询  now  data||+1M

  1. GET /website/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "range" : {
  7. "post_date": {
  8. "gte" : "2020-01-01",
  9. "lt": "2020-09-09||+1h"
  10. }
  11. }
  12. }
  13. }
  14. }
  15. }

4. 组合查询(bool)

SQL:SELECT * FROM products WHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3") AND (price != 30)

  1. GET /my_store/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "bool" : {
  7. "should" : [
  8. { "term" : {"price" : 20}},
  9. { "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
  10. ],
  11. "must_not" : {
  12. "term" : {"price" : 30}
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }

SQL:SELECT * FROM products WHERE productID = "KDKE-B-9947-#kL5" OR (productID = "JODL-X-1937-#pV7" AND price = 30)

  1. GET /my_store/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "bool" : {
  7. "should" : [
  8. { "term" : {"productID" : "KDKE-B-9947-#kL5"}},
  9. { "bool" : {
  10. "must" : [
  11. { "term" : {"productID" : "JODL-X-1937-#pV7"}},
  12. { "term" : {"price" : 30}}
  13. ]
  14. }}
  15. ]
  16. }
  17. }
  18. }
  19. }
  20. }

5. 处理null值(exists)

插入测试数据

  1. POST /posts/_bulk
  2. { "index": { "_id": "1" }}
  3. { "tags" : ["search"] }
  4. { "index": { "_id": "2" }}
  5. { "tags" : ["search", "open_source"] }
  6. { "index": { "_id": "3" }}
  7. { "other_field" : "some data" }
  8. { "index": { "_id": "4" }}
  9. { "tags" : null }
  10. { "index": { "_id": "5" }}
  11. { "tags" : ["search", null] }

存在查询
SQL:SELECT tags FROM posts WHERE tags IS NOT NULL

  1. GET /posts/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "exists" : { "field" : "tags" }
  7. }
  8. }
  9. }
  10. }

缺失查询
SQL:SELECT tags FROM posts WHERE tags IS NULL

  1. GET /posts/_search
  2. {
  3. "query" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "bool": {
  7. "must_not":{"exists" : { "field" : "tags" }}
  8. }
  9. }
  10. }
  11. }
  12. }

全文搜索

插入测试数据

  1. POST /my_index/my_type/_bulk
  2. { "index": { "_id": 1 }}
  3. { "title": "The quick brown fox" }
  4. { "index": { "_id": 2 }}
  5. { "title": "The quick brown fox jumps over the lazy dog" }
  6. { "index": { "_id": 3 }}
  7. { "title": "The quick brown fox jumps over the quick dog" }
  8. { "index": { "_id": 4 }}
  9. { "title": "Brown fox brown dog" }

1. match

单个词查询

执行过程:

  1. 检查字段类型
  2. 分析查询字符串
  3. 调用term查询,去倒排索引中查询包含quick的文档
  4. 为每个文档评分并排序
  1. GET /my_index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "title": "QUICK!"
  6. }
  7. }
  8. }

检查字段类型

  1. GET /_analyze
  2. {
  3. "text": "QUICK!"
  4. }

分析查询字符串,调用term查询,去倒排索引中查询包含quick的文档

  1. GET /my_type/_search
  2. {
  3. "query": {
  4. "term": {
  5. "title": "quick"
  6. }
  7. }
  8. }

多词查询

  1. GET /my_index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "title": "BROWN DOG!"
  6. }
  7. }
  8. }
  9. GET /my_index/_search
  10. {
  11. "query": {
  12. "bool": {
  13. "should": [
  14. {"term": {"title": "brown"}},
  15. {"term":{"title":"dog"}}
  16. ]
  17. }
  18. }
  19. }

为每个文档评分并排序

总结:被匹配的此项越多,文档越相关,排名越靠前

operator:修改匹配关系

  1. GET /my_index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "title": {
  6. "query": "BROWN DOG!",
  7. "operator": "and"
  8. }
  9. }
  10. }
  11. }
  12. GET /my_index/_search
  13. {
  14. "query": {
  15. "bool": {
  16. "must": [
  17. {"term": {"title": "brown"}},
  18. {"term":{"title":"dog"}}
  19. ]
  20. }
  21. }
  22. }

2. bool(组合查询)

查询包含quick,但不包含lazy的所有文档,如果包含should里的字段,则该文章相关度更高

  1. GET /my_index/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": { "match": { "title": "quick" }},
  6. "must_not": { "match": { "title": "lazy" }},
  7. "should": [
  8. { "match": { "title": "brown" }},
  9. { "match": { "title": "dog" }}
  10. ]
  11. }
  12. }
  13. }

3. match_phrase(短语匹配)

  1. GET /my_index/_search
  2. {
  3. "query": {
  4. "match_phrase": {
  5. "title": "quick brown fox"
  6. }
  7. }
  8. }

分页(深度分页)from+size

缺点:

  • 效率低。比如from=5000,size=100,es需要在各个分片上匹配排序并得到5000+100条有效数据,然后在结果集中取最后100条结果。
  • 最大可查询条数为1W条。ES目前默认支持的skin值max_result_window=10000,当from+size>max_result_window时,ES就会返回错误。
  • 解决办法:使用scroll(游标查询)
  1. {
  2. "query": {
  3. "match_all": {}
  4. },
  5. "from": 0,
  6. "size": 1
  7. }

from:从第几个商品开始查,最开始是 0

size:要查几个结果

排序

根据主文档字段排序

  1. {
  2. "query": {
  3. "match_all": {
  4. }
  5. },
  6. "sort": [
  7. {
  8. "age": {
  9. "order": "desc"
  10. }
  11. }
  12. ]
  13. }

内嵌文档字段排序
主查询中的过滤条件并不会把不符合条件的内部嵌套文档过滤掉,以至于排序嵌套文档时,还是按照全部的嵌套文档排序

  1. {
  2. "query": {
  3. "nested": {
  4. "path": "shgx",
  5. "query": {
  6. "range": {
  7. "shgx.age": {
  8. "lt": 50
  9. }
  10. }
  11. }
  12. }
  13. },
  14. "sort": [
  15. {
  16. "shgx.age": {
  17. "nested_path": "shgx",
  18. "order": "desc",
  19. "nested_filter": {
  20. "range": {
  21. "shgx.age": {
  22. "lt": 50
  23. }
  24. }
  25. }
  26. }
  27. }
  28. ]
  29. }

游标查询(scroll)

启动游标查询

CET /host/_search?scroll=1m

scroll=1m表示游标查询窗口保持1分钟,如果一次取的数据量大可以设置大一些的时间;返回字段包含一个scroll_id,接下来用这个字段获取后续值


循环获取余下值

  1. GET /_search/scroll
  2. {
  3. "scroll": "1m"
  4. "scroll_id": scroll_id
  5. }

python操作

  1. from elasticsearch import Elasticsearch
  2. es = Elasticsearch(['localhost:9200'])
  3. # 1.启动游标
  4. queryData = es.search("internal_isop_log", body=dsl_body, scroll='1m', size=1000)
  5. # 获取scroll_id
  6. hits_list = queryData.get("hits").get("hits")
  7. scroll_id = queryData['_scroll_id']
  8. # 2.循环获取
  9. total = queryData.get("hits").get("total").get('value')
  10. for i in range(int(total / 1000)):
  11. ss = {'scroll': '1m', 'scroll_id': scroll_id}
  12. res = self.es.scroll(body=ss)

模糊查询

创建索引,设置postcode字段使用keyword规则 ❗模糊查询会匹配倒排表里的字段 ❗

  1. PUT /address
  2. {
  3. "mappings": {
  4. "properties": {
  5. "postcode": {
  6. "type": "text",
  7. "analyzer": "keyword"
  8. }
  9. }
  10. }
  11. }

导入测试数据

  1. PUT /address/_bulk
  2. { "index": { "_id": 1 }}
  3. { "postcode": "W1V 3DG" }
  4. { "index": { "_id": 2 }}
  5. { "postcode": "W2F 8HW" }
  6. { "index": { "_id": 3 }}
  7. { "postcode": "W1F 7HW" }
  8. { "index": { "_id": 4 }}
  9. { "postcode": "WC1N 1LZ" }
  10. { "index": { "_id": 5 }}
  11. { "postcode": "SW5 0BE" }

倒排表

Term

Doc IDs

"SW5 0BE"

5

"W1F 7HW"

3

"W1V 3DG"

1

"W2F 8HW"

2

"WC1N 1LZ"

4

前缀匹配(prefix)
匹配postcode字段以“W1”开头的文档

  1. GET /address/_search
  2. {
  3. "query": {
  4. "prefix": {
  5. "postcode": "W1"
  6. }
  7. }
  8. }

通配符查询(wildcard)

  1. GET /address/_search
  2. {
  3. "query": {
  4. "wildcard": {
  5. "postcode": "W?F*HW"
  6. }
  7. }
  8. }

正则匹配(regexp)

  1. GET /address/_search
  2. {
  3. "query": {
  4. "regexp": {
  5. "postcode": "W[0-9].+"
  6. }
  7. }
  8. }

不配置分词规则带来的影响

栗子:title字段为“Quick brown fox” ,倒排索引中会生成: quick 、 brown 和 fox

{ "regexp": { "title": "br.*" }}

可以匹配

{ "regexp": { "title": "Qu.*" }}

匹配不到:quick为小写

{ "regexp": { "title": "quick br*" }}

匹配不到:quick和brown是分开的

三、聚合分组

ElasticSearch除了致力于搜索之外,也提供了聚合实时分析数据的功能,透过聚合,我们可以得到一个数据的概览,分析和总结全套的数据

对相同的数据进行 搜索/过滤 + 分析,两个愿望一次满足

聚合的两个主要的概念,分别是 指标

桶(Buckets) : 满足特定条件的文档的集合

  • 当聚合开始被执行,每个文档会决定符合哪个桶的条件,如果匹配到,文档将放入相应的桶并接着进行聚合操作(比如一个员工属于男性桶或者女性桶)
  • 桶可以被嵌套在其他桶里面(北京能放在中国桶里)

指标(Metrics) : 对桶内的文档进行统计计算

  • 桶能让我们划分文档到有意义的集合, 但是最终我们需要的是对这些桶内的文档进行一些指标的计算
  • 指标通常是简单的数学运算(像是min、max、avg、sum)

执行顺序及聚合写法

当query和aggs一起存在时,会先执行query的主查询,主查询query执行完后会搜出一批结果,而这些结果才会被拿去aggs拿去做聚合

伪代码结构 

  1. {
  2. "query": { ... },
  3. "size": 0,
  4. "aggs": {
  5. "custom_name1": { // 自定义桶1名称
  6. "桶": { ... } // 桶1查询语句
  7. },
  8. "custom_name2": { // 一个aggs里可以有多个聚合
  9. "桶": { ... }
  10. },
  11. "custom_name3": {
  12. "桶": {
  13. .....
  14. },
  15. "aggs": { // aggs可以嵌套在别的aggs里面
  16. "in_name": { // 记得使用aggs需要先自定义一个name
  17. "桶": { ... } // in_name的桶作用的文档是custom_name3的桶的结果
  18. }
  19. }
  20. }
  21. }
  22. }

指标聚合(Metrics)

1. max、min、sum、avg

例:查询所有记录中年龄的最大值

  1. POST /book1/_search?pretty
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "maxage": {
  6. "max": {
  7. "field": "age"
  8. }
  9. }
  10. }
  11. }

结果

  1. {
  2. "took": 4,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "maxage": {
  17. "value": 54
  18. }
  19. }
  20. }

例:查询所有记录的平均年龄是多少,并对平均年龄加10

  1. POST /book1/_search?pretty
  2. {
  3. "size":0,
  4. "aggs": {
  5. "avg_age": {
  6. "avg": {
  7. "script": {
  8. "source": "doc.age.value"
  9. }
  10. }
  11. },
  12. "avg_age10": {
  13. "avg": {
  14. "script": {
  15. "source": "doc.age.value + 10"
  16. }
  17. }
  18. }
  19. }
  20. }

结果:

  1. {
  2. "took": 3,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "avg_age": {
  17. "value": 7.585365853658536
  18. },
  19. "avg_age10": {
  20. "value": 17.585365853658537
  21. }
  22. }
  23. }

例:为缺失值指定值。如未指定,缺失该字段值的文档将被忽略

  1. POST /book1/_search?pretty
  2. {
  3. "size":0,
  4. "aggs": {
  5. "sun_age": {
  6. "avg": {
  7. "field":"age",
  8. "missing":15
  9. }
  10. }
  11. }
  12. }

结果

  1. {
  2. "took": 12,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "sun_age": {
  17. "value": 12.847826086956522
  18. }
  19. }
  20. }
2. Value count

统计某字段有值的文档数

  1. POST /book1/_search?size=0
  2. {
  3. "aggs":{
  4. "age_count":{
  5. "value_count":{
  6. "field":"age"
  7. }
  8. }
  9. }
  10. }

结果

  1. {
  2. "took": 1,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "age_count": {
  17. "value": 38
  18. }
  19. }
  20. }
3. cardinality

去重计数

  1. POST /book1/_search?size=0
  2. {
  3. "aggs":{
  4. "age_count":{
  5. "value_count":{
  6. "field":"age"
  7. }
  8. },
  9. "name_count":{
  10. "cardinality":{
  11. "field":"age"
  12. }
  13. }
  14. }
  15. }

结果

  1. {
  2. "took": 16,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "name_count": {
  17. "value": 11
  18. },
  19. "age_count": {
  20. "value": 38
  21. }
  22. }
  23. }
4. stats

统计 count max min avg sum 5个值

  1. POST /book1/_search?size=0
  2. {
  3. "aggs":{
  4. "age_count":{
  5. "stats":{
  6. "field":"age"
  7. }
  8. }
  9. }
  10. }

结果

  1. {
  2. "took": 12,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "age_count": {
  17. "count": 38,
  18. "min": 1,
  19. "max": 54,
  20. "avg": 12.394736842105264,
  21. "sum": 471
  22. }
  23. }
  24. }
5.Extended stats

高级统计,比stats多4个统计结果: 平方和、方差、标准差、平均值加/减两个标准差的区间。

  1. POST /book1/_search?size=0
  2. {
  3. "aggs":{
  4. "age_stats":{
  5. "extended_stats":{
  6. "field":"age"
  7. }
  8. }
  9. }
  10. }

结果

  1. {
  2. "took": 8,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "age_stats": {
  17. "count": 38,
  18. "min": 1,
  19. "max": 54,
  20. "avg": 12.394736842105264,
  21. "sum": 471,
  22. "sum_of_squares": 11049,
  23. "variance": 137.13365650969527,
  24. "std_deviation": 11.710408041981085,
  25. "std_deviation_bounds": {
  26. "upper": 35.81555292606743,
  27. "lower": -11.026079241856905
  28. }
  29. }
  30. }
  31. }

桶聚合(Buckets)

1. Terms Aggregation

针对某个field的值进行分组,field有几种值就分成几组

  • terms桶在进行分组时,会爲此field中的每种值创建一个新的桶
  • 要注意此 "terms桶" 和平常用在主查询query中的 "查找terms" 是不同的东西

测试数据

  1. { "color": "red" }
  2. { "color": "green" }
  3. { "color": ["red", "blue"] }

dsl语句

  1. {
  2.    "query": {
  3.        "match_all": {}
  4.   },
  5.    "size": 0,
  6.    "aggs": {
  7. "my_name": {
  8.            "terms": {
  9.           "field": "color" //使用color来进行分组
  10.           }
  11.       }
  12.   }
  13. }

结果

  1. "aggregations": {
  2.    "my_name": {
  3.        "doc_count_error_upper_bound": 0,
  4.        "sum_other_doc_count": 0,
  5.        "buckets": [
  6.           {
  7.                "key": "blue",
  8.                "doc_count": 1
  9.           },
  10.           {
  11.                "key": "red",
  12.                "doc_count": 2  //表示color为red的文档有2个,此例中就是 {"color": "red"} 和 {"color": ["red", "blue"]}这两个文档
  13.           },
  14.           {
  15.                "key": "green",
  16.                "doc_count": 1
  17.           }
  18.       ]
  19.   }
  20. }

2. Filter Aggregation

对满足过滤查询的文档进行聚合计算

要注意此处的 "filter桶" 和用在主查询query的 "过滤filter" 的用法是一模一样的,都是过滤,不过差别是 "filter桶" 会自己给创建一个新的桶,而不会像 "过滤filter" 一样依附在query下,因为filter桶毕竟还是一个聚合桶,因此他可以和别的桶进行嵌套,但他不是依附在别的桶上

测试数据同上

dsl语句

  1. {
  2.    "query": {
  3.        "match_all": {}
  4.   },
  5.    "size": 0,
  6.    "aggs": {
  7.        "my_name": {
  8.            "filter": { //因为他用法跟一般的过滤filter一样,所以也能使用bool嵌套
  9.                "bool": {
  10.                    "must": {
  11.                        "terms": { //注意此terms是查找terms,不是terms桶
  12.                            "color": [ "red", "blue" ]
  13.                       }
  14.                   }
  15.               }
  16.           }
  17.       }
  18.   }
  19. }

结果

  1. "aggregations": {
  2. "my_name": {
  3. "doc_count": 2 //filter桶计算出来的文档数量
  4. }
  5. }

3. Filters Aggregation

多个过滤组聚合计算

例:分别统计包含‘test’,和‘里’的文档的个数

  1. POST book1/_search?size=0
  2. {
  3. "aggs":{
  4. "age_terms":{
  5. "filters":{
  6. "filters":{
  7. "test":{
  8. "match":{"name":"test"}
  9. },
  10. "china":{
  11. "match":{"name":"里"}
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }

结果:

  1. {
  2. "took": 3,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 5,
  6. "successful": 5,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 41,
  12. "max_score": 0,
  13. "hits": []
  14. },
  15. "aggregations": {
  16. "age_terms": {
  17. "buckets": {
  18. "china": {
  19. "doc_count": 13
  20. },
  21. "test": {
  22. "doc_count": 5
  23. }
  24. }
  25. }
  26. }
  27. }
4. Top_hits Aggregation

在某个桶底下找出这个桶的前几笔hits,返回的hits格式和主查询query返回的hits格式一模一样

参数

  • from、size
  • sort : 设置返回的hits的排序
    • 要注意,假设在主查询query里已经对数据设置了排序sort,此sort并不会对aggs里面的数据造成影响,也就是说主查询query查找出来的数据会先丢进aggs而非先经过sort,因此就算主查询设置了sort,也不会影响aggs数据里的排序因此如果在top_hits桶里的返回的hits数据想要排序,需要自己在top_hits桶里设置sort
    • 如果没有设置sort,默认使用主查询query所查出来的_score排序
  • _source : 设置返回的字段

测试数据

  1. { "color": "red", "price": 100 }
  2. { "color": ["red", "blue"], "price": 1000 }

使用terms桶分组,再使用top_hits桶找出每个group里面的price最小的前5笔hits

  1. {
  2.    "query": {
  3.        "match_all": {}
  4.   },
  5.    "size": 0,
  6.    "aggs": {
  7.        "my_name": {
  8.            "terms": {
  9.                "field": "color"
  10.           },
  11.            "aggs": {
  12.                "my_top_hits": {
  13.                    "top_hits": {
  14.                        "size": 5,
  15.                        "sort": {
  16.                            "price": "asc"
  17.                       }
  18.                   }
  19.               }
  20.           }
  21.       }
  22.   }
  23. }

结果

  1. "aggregations": {
  2.    "my_name": {
  3.        "doc_count_error_upper_bound": 0,
  4.        "sum_other_doc_count": 0,
  5.        "buckets": [
  6.           {
  7.                "key": "red",
  8.                "doc_count": 2,  //terms桶计算出来的color为red的文档数
  9.                "my_top_hits": {
  10.                    "hits": {  //top_hits桶找出color为red的这些文档中,price从小到大排序取前5
  11.                        "total": 2,
  12.                        "max_score": null,
  13.                        "hits": [
  14.                           {
  15.                                "_score": null,
  16.                                "_source": { "color": "red", "price": 100 },
  17.                                "sort": [ 100 ]
  18.                           },
  19.                           {
  20.                                "_score": null,
  21.                                "_source": { "color": [ "red", "blue" ], "price": 1000 },
  22.                                "sort": [ 1000 ]
  23.                           }
  24.                       ]
  25.                   }
  26.               }
  27.           },
  28.           {
  29.                "key": "blue",
  30.                "doc_count": 1,  //terms桶计算出来的color为blue的文档数
  31.                "my_top_hits": {
  32.                    "hits": { //top_hits桶找出的hits
  33.                        "total": 1,
  34.                        "max_score": null,
  35.                        "hits": [
  36.                           {
  37.                                "_source": {
  38.                                    "color": [ "red", "blue" ], "price": 1000 },
  39.                                "sort": [ 1000 ]
  40.                           }
  41.                       ]
  42.                   }
  43.               }
  44.           }
  45.       ]
  46.   }
  47. }

5. Date_histogram Aggregation

时间直方图(柱状)聚合

参数

  • time_zone:"+08:00":设置市区(东八区),不指定会影响分组时间错误
  • interval:聚合时间间隔
    • year(1y)年
    • quarter(1q)季度
    • month(1M)月份
    • week(1w)星期
    • day(1d)天
    • hour(1h)小时
    • minute(1m)分钟
    • second(1s)秒
  • format:指定返回时间格式

dsl语句

  1. {  
  2. "query": {    
  3. "match_all": {} 
  4. },
  5. "size": 0,
  6. "aggs": {
  7. // 自己取的聚合名字
  8. "group_by_grabTime": {
  9. // es提供的时间处理函数
  10. "date_histogram": {
  11. // 需要聚合分组的字段名称, 类型需要为date, 格式没有要求
  12. "field": "@timestamp",
  13. // 按什么时间段聚合, 这里是5分钟, 可用的interval在上面给出
  14. "interval": "5m",
  15. // 设置时区, 这样就相当于东八区的时间
  16. "time_zone": "+08:00",
  17. // 返回值格式化,HH大写,不然不能区分上午、下午
  18. "format": "yyyy-MM-dd HH",
  19. // 为空的话则填充0
  20. "min_doc_count": 0,
  21. // 需要填充0的范围
  22. "extended_bounds": {
  23. "min": 1533556800000,
  24. "max": 1533806520000
  25. }
  26. },
  27. // 聚合
  28. "aggs": {
  29. // 自己取的名称
  30. "group_by_status": {
  31. // es提供
  32. "terms": {
  33. // 聚合字段名
  34. "field": "LowStatusOfPrice"
  35. }
  36. }
  37. }
  38. }
  39. }
  40. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/807281
推荐阅读
相关标签
  

闽ICP备14008679号