美文网首页
Elasticsearch学习(一)

Elasticsearch学习(一)

作者: 笔记本一号 | 来源:发表于2020-05-25 10:17 被阅读0次

    es的官方中文文档
    https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
    概念
    es是基于Lucene,纯java语言编写的分布式,可扩展,近实时性的高性能搜索引擎和数据分析引擎

    es基础构成

    • document
      es中数据存储的最小单元,对应数据库的一行数据
    • Index
      有具有相同字段的文档列表组成,对应数据库的一个表,一个索引由一个或者多个分片组成
    • type
      文档类型,这个我们可以不用记,es后面的版本要把type去掉。之前的版本中,索引和文档中间还有个类型的概念,每个索引下可以建立多个类型,文档存储时需要指定index和type。从6.0.0开始单个索引中只能有一个类型,7.0.0以后将将不建议使用,8.0.0 以后完全不支持。在7.0开始,一个索引只能建一个Type为_doc。
    • shards
      分片。当索引数据太大时,受限于单个节点的磁盘,内存,处理能力等资源,需要将索引的数据水平拆分,拆分后形成的每一个分片回落到不一样的服务节点上,这样显著提升了es的性能,索引创建时需要指定分片,一旦分片被指定就无法更改
    • replicas
      副本。是主分片的备份分片,副本主要是用于主分片的数据备份,同时也对外提供数据查询服务。副本分片提升了es的高可用性
    分片shard和es集群的高可用高性能

    分片的概念和kafka的分区很像,既有副本又各自拥有不同的数据并且分散在不同的节点,index就是这些分片的topic。

    一个索引中的数据保存通过hash取余决定保存在哪分片中,相当于水平分表也类似于kafka的分区,分片有主分片和副本分片,一个主分片可以设置多个副本分片,在es集群中每个主分片存储了es的部分数据,副本分片主要是用于备份主分片的数据,主分片分布在es的各个节点上,而各个主分片的副本分片也会分布到和主分片不同的节点上,当集群中某个节点宕机时,分布在其他节点的副本分片就会顶替原来的主分片,这个体现了es的高可用性。

    由于分片分散在各个不同的节点上,每个节点都有能力处理任意请求, 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上,所以其请求压力和数据分析压力也会分散到集群的各个节点上,实现了es的高性能。我们最好通过轮询的方式访问集群的节点

    分片的原理就和数据库的水平分表和kafka的分区是一个道理的,既能保证高新南

    下图的流程展示es集群的高可用

    图一:es集群中有三个节点,三个主分片,三个副本分片,也就是每个分片拥有一个副本分片

    图一

    图二:主节点宕机,node2通过选举称为新主节点

    图二

    图三:挂掉的node1的副本分片存储在node3上,集群将副本分片P0调整为主分片,这样node1的数据就恢复回来了

    图三

    图四:es集群将为创建P0的副本分片,和重新创建和node1一起挂掉的R1副本分片,并让它们保存在和自己主分片不一样的节点上,也就是P0副本分片保存在node2上,R1副本分片保存在node3上,下次就算是在宕机,其中的一个节点存在有其他备份分片,保证了数据的不丢失,这就是es的高可用性

    图四

    数据被存储到哪个分片是由公式决定的:
    shard = hash(routing) % number_of_primary_shards
    routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值

    分片的实时性和查询性能

    refresh:在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh,也就是数据在jvm内存写入文件系统缓存中并形成段的过程。 在Elasticsearch的jvm内和磁盘之间是文件系统缓存,写入的数据会先落入jvm内存中,在jvm内存中的数据是没有进行分段的无法提供搜索,当内存的数据到达一定量或者时间就和进行一次refresh,然后缓存数据到文件系统缓存中形成段,然后将jvm内存清理,此时数据才可以提供搜索, Elasticsearch定时刷新(flush)文件系统缓存中的数据到磁盘中形成提交点。es默认每秒中执行一次refresh

    默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文档的变化并不是立即对搜索可见,但会在一秒之内变为可见可搜索。

    flush:这种缓存的机制给es带来了性能上的提升,但是也带来了丢失数据的风险,所以es添加了事务日志,事务日志主要记录还未持久化到硬盘的数据,当日志文件大小达到一定量时(默认512MB),或者超过固定时间(默认5秒),es就会触发一次刷新(flush),将jvm内存和文件系统缓存的数据持久化,然后删除日志文件,并创建新的日志文件。

    fsync:每个新段在文件系统缓存被持久化的过程叫做fsync

    有时候我们创建了一个文档然后尝试搜索它,但却没有搜到。这个问题的解决办法是用 refresh API 执行一次手动刷新:

    POST /_refresh  //刷新所有的索引
    POST /index_name/_refresh //只刷新(Refresh) 特定索引
    

    es写性能优化

    降低刷新频率(会影响实时性)
      1. 提高写性能,我们可以启动多线程去进行写操作
      1. 除了启动多线程外还可以通过调整刷新频率来提升性能。

    虽然刷新(refresh)是比提交轻量很多的操作,但它还是会有性能开销,并不是所有的情况都需要每秒刷新。如果你想优化读写速度而不是近实时搜索,可以通过设置refresh_interval, 降低每个索引的刷新频率:

    PUT /my_logs
    {
        "settings": {
            "refresh_interval": "30s"  //每30秒刷新 my_logs 索引,默认是每秒刷新
        }
    }
    

    refresh_interval 是可以进行动态更新的,就是说在生产环境中,当你正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来:

    PUT /my_logs/_settings
    { "refresh_interval": -1 } //关闭实时更新
    
    PUT /my_logs/_settings
    { "refresh_interval": "1s" }//开启每秒更新
    

    refresh_interval 需要一个 持续时间 值, 例如 1s (1 秒) 或 2m (2 分钟)。 一个绝对值 1 表示的是 1毫秒 (会使你的集群陷入瘫痪)。

      1. 修改内存缓存大小(indices.memory.index_buffer_size)。

    jvm内存缓存的数据满了或者是超过固定时间就会进行刷新操作,调整内存缓存大小可以有效的降低刷新频率
    在elasticsearch.yml中可以这样设置:

    indices.memory.index_buffer_size: 20%(默认是堆内存的10%)
    indices.memory.min_index_buffer_size: 96mb(默认是48mb)
    

    已经索引好的文档会先存放在内存缓存中,等待被写到到段(segment)中。缓存满的时候会触发段刷盘(吃i/o和cpu的操作)。默认最小缓存大小为48m,不太够,最大为堆内存的10%。对于大量写入的场景也显得有点小。

      1. 修改事务日志(translog)的刷新频率(fsync)(index.translog.sync_interval)和大小(index.translog.flush_threshold_size)

    日志中记录了还在缓存中并未形成段的数据,会定时或者超过一定量后进行刷新
    在elasticsearch.yml中可以这样设置:

    index.translog.sync_interval:30s(默认5s)。
    index.translog.flush_threshold_size:700mb(默认512mb)
    index.translog.durability:async(默认request) //通过异步提交日志,不过可以会在宕机时丢失数据
    
      1. _id字段的使用,应尽可能避免自定义_id, 以避免针对ID的版本管理;建议使用ES的默认ID生成策略或使用数字类型ID做为主键。

    es读性能优化

    • 1.合理的分片的数量,分片数量越多每个分片的数据范围就越小,合理的分片数量能有效的提升每个分片的查询性能
    • 2. 当机器内存小于64G时,遵循通用的原则,50%给ES,50%留给lucene。

    内存对于 Elasticsearch 来说绝对是重要的,它可以被许多内存数据结构使用来提供更快的操作。但是说到这里, 还有另外一个内存消耗大户 非堆内存 (off-heap):Lucene。

    Lucene 被设计为可以利用操作系统底层机制来缓存内存数据结构。 Lucene 的段是分别存储到单个文件中的。因为段是不可变的,这些文件也都不会变化,这是对缓存友好的,同时操作系统也会把这些段文件缓存起来,以便更快的访问。

    Lucene 的性能取决于和操作系统的相互作用。如果你把所有的内存都分配给 Elasticsearch 的堆内存,那将不会有剩余的内存交给 Lucene。 这将严重地影响全文检索的性能。

    标准的建议是把 50% 的可用内存作为 Elasticsearch 的堆内存,保留剩下的 50%。

      1. 当机器内存大于64G时,遵循以下原则:
      1. 如果主要的使用场景是全文检索, 那么建议给ES Heap分配 4~32G的内存即可;其它内存留给操作系统, 供lucene使用(segments cache), 以提供更快的查询性能。
      2. 如果主要的使用场景是聚合或排序, 并且大多数是numerics, dates, geo_points 以及not_analyzed的字符类型, 建议分配给ES Heap分配 4~32G的内存即可,其它内存留给操作系统,供lucene使用(doc values cache),提供快速的基于文档的聚类、排序性能。
      3. 如果使用场景是聚合或排序,并且都是基于analyzed 字符数据,这时需要更多的 heap size, 建议机器上运行多ES实例,每个实例保持不超过50%的ES heap设置(但不超过32G,堆内存设置32G以下时,JVM使用对象指标压缩技巧节省空间),50%以上留给lucene。
    • 关闭交换分区,防止内存发生交换导致性能下降 通过执行swapoff -a或者通过: 在elasticsearch.yml 中 bootstrap.memory_lock: true, 以保持JVM锁定内存,保证ES的性能。

    es的锁机制

    由于es需要处理一定的并发量的写操作,es是使用的乐观锁,主要是使用java的CAS技术实现乐观锁

    正排索引

    就是利用文档id查询文档内容,也就是通过key去查value

    倒排索引

    就是通过value去查key,关于倒排索引这里有一篇不错的文章可以供大家参考https://blog.csdn.net/qq_21312297/article/details/102496833

    es索引的过程
    es是先通过term Dictionary将每个单词出现在文档的位置地址这个过程是倒排索引,然后通过地址去查询文档,这个是正排索引,es就是倒排索引和正排索引的结合

    term Dictionary(单词字典):记录了所有文档的单词,es储存的文档内容越大词典也就越大,还记录了单词是放在哪些文档上的关联信息,通常term Dictionary会被拆分成单词的前缀组成一颗B+树,每个叶子节点的单词会记录着单词所在文档的位置地址

    Posting List:记录了单词对应文档的集合,由Posting组成,而Posting中包含了文档id,单词出现频率,文档中单词的位置,单词在文档开始和结束的位置

    以下是倒排索引的过程
    文档字段类型
    核心类型 字符串类型 string,text,keyword
    整数类型 integer,long,short,byte
    浮点类型 double,float,half_float,scaled_float
    逻辑类型 boolean
    日期类型 date
    范围类型 range
    二进制类型 binary
    复合类型 数组类型 array
    对象类型 object
    嵌套类型 nested
    地理类型 地理坐标类型 geo_point
    地理地图 geo_shape
    特殊类型 IP类型 ip
    范围类型 completion
    令牌计数类型 token_count
    附件类型 attachment
    抽取类型 percolator
    

    基础语句

    以下省略 http://localhost:9200

    index操作

    创建index:

    put  /index_name
    {
       "settings" : {
          "number_of_shards" : 3,
          "number_of_replicas" : 1
       }
    }
    

    查看index:

    get  /_cat/indices
    

    删除index:

    delete /index_name
    
    document操作

    创建id为2的文档:

    DELETE /index_name/doc/2
    

    创建id为1的文档:

    put /index_name/doc/1
    {
    "name":"es",
    "user":"test"
    }
    

    创建自带id的文档:

    post /index_name/doc/
    {
    "name":"es",
    "user":"test"
    }
    

    批量创建文档:

    put /u/_bulk
    {"index":{"_id":3}}
    {"username":"james","code":23,"age":32,"country":"usa","job":"basketball"}
    {"index":{"_id":4}}
    {"username":"haden","code":15,"age":30,"country":"usa","job":"basketball"}
    {"index":{"_id":5}}
    {"username":"bingbing","code":999,"age":35,"country":"chn","job":"act"}
    {"index":{"_id":6}}
    {"username":"susu","code":999,"age":25,"country":"chn","job":"great"}
    {"index":{"_id":7}}
    {"username":"hu","code":999,"age":36,"country":"chn","job":"act"}
    

    批量修改文档:

    POST _bulk
    {"update":{"_index":"test","_type":"product","_id":1}}
    {"doc":{ "price" : 5200, "productName" : "苹果11","memory":"128G" }}
    {"update":{"_index":"test","_type":"product","_id": 2 }}
    {"doc":{ "price" : 3100, "productName" : "小米10","memory":"268G" }}
    {"update":{"_index":"test","_type":"product", "_id": 3 }}
    {"doc":{ "price" : 1300, "productName" : "酷派大神","memory":"16G" }}
    {"update":{"_index":"test","_type":"product", "_id": 4 }}
    {"doc":{ "price" : 730, "productName" : "魅蓝note3","memory":"32G" }}
    {"update":{"_index":"test","_type":"product", "_id": 6 }}
    {"doc":{ "price" : 10000, "productName" : "macBook Pro","memory":"521G" }}
    {"update":{"_index":"test","_type":"product", "_id": 7 }}
    {"doc":{ "price" : 6500, "productName" : "华为P40","memory":"128G" }}
    {"update":{"_index":"test","_type":"product","_id": 8 }}
    {"doc":{ "price" : 3100, "productName" : "Ipad Air3","memory":"64G" }}
    

    批量查询:

    post /_mget
    {
        "docs": [
            {
                "_index": "test_index",
                "_type": "doc",
                "_id": "1"
            },
            {
                "_index": "test_index",
                "_type": "doc",
                "_id": "Ai9cM3IBEyMN0HxifBpI"
            }
        ]
    

    修改文档:

    POST /u/_doc/5/_update
    {
       "doc":{
        "age":41,
        "username":"kate"
       }
    }
    

    根据查询的结果更改文档字段:

    POST /u/_doc/_update_by_query
    {
        "script":{
        "source":"ctx._source['brith']='1990-11-11 12:00:00'"
        },
       "query":{
        "match_all":{
        }
       }
    }
    

    新增文档字段:

    PUT /u/_mapping
    {
       "properties":{
        "brith":{
            "type":"date",
            "format": "yyyy-MM-dd HH:mm:ss"
        }
       }
    }
    
    分词器

    分词就是将文本转化为一系列单词的过程,也叫做文本分析,在es中称为Analysis,es默认的Analysis是standard
    Analysis由三部分组成:
    Character Filters:对原始文本进行处理,去掉一些特殊的符号标签,例如去除html的特殊标记符
    Tokenizer:将原始文本按照一定的规则切分成单词
    Toker Filters:对Tokenizer处理的单词进一步加工,例如大小写转换,删除没有意义的词等

    分词器选择并测试:

    post /_analyze
    {
       "analyzer":"simple",//选择simple分词器
       "text":"elasticsearch是世界最好的搜索引擎"
        
    }
    

    es内置分词器:
    Standard - 默认分词器,按词切分,小写处理
    Simple - 按照非字母切分(符号被过滤), 小写处理
    Stop - 小写处理,停用词过滤(the,a,is)
    Whitespace - 按照空格切分,不转小写
    Keyword - 不分词,直接将输入当作输出
    Patter - 正则表达式,默认\W+(非字符分割)
    Language - 提供了30多种常见语言的分词器
    Customer 自定义分词器

    自定义分词器:

    put /index_name_2
    {
    "settings":{
        "analysis":{
                "analyzer":{
                    "my_analysis":{
                              "type":"custom",
                               "tokenizer":"standard",
                               "char_filter":["html_strip","to_and"],
                                "filter":["lowercase","my_stopwords"]
                        }
                    },
                    "char_filter": {
                "to_and": {
                    "type": "mapping",
                    "mappings": ["& => and"]
                }
            },
            "filter": {
                "my_stopwords": {
                    "type": "stop",
                    "stopwords": ["the", "a"]
                            }
                    }
                }
        }
    }  
    

    中文分词器:
    IK - 支持中英文单词分词,支持ik_smart,ik_maxword的模式,支持自定义词库、支持热更新单词词典
    jieba - python最流行的分词器,支持繁体分词,自定义词典等

    Mapping

    Mapping类似数据库表数据类型定义,Mapping可以定义index下的字段名,字段类型

    这里不写了,属性太多,到官方网站看文档去吧
    https://www.elastic.co/guide/en/elasticsearch/reference/master/mapping.html

    Search API

    URI Search

    q:指定URL查询条件
    df(default field):指定查询的字段,如果不写,es 会查询所有字段或者是q中指定的字段
    sort:排序
    timeout:指定超时时间,默认不超时
    from,size:用于分页

    GET /u/_search?q=basketball
    GET /u/_search?q=job:basketball mvp//查询出所有job是basketball和mvp的文档
    GET /u/_search?q=job:"basketball mvp"//查询出所有job是basketball mvp的文档
    GET /u/_search?q=job:(basketball mvp)//查询job:basketball或者job:mvp
    GET /u/_search?q=user.id:8a4f500d
    GET /u/_search?q=basketball&df=job&sort=age:asc&from=1&size=3&timeout=1s//df指定q的值basketball从job字段查,分页从第一页开始,每页3条记录,查询时间不能超过1秒,超过一秒就退出查询
    
    布尔操作:

    要大写,不能小写
    AND:&&
    OR:||
    NOT:!

    GET /u/_search?q=basketball AND mvp //查询出所有包含basketball 并且同时有mvp 的字段
    GET /u/_search?q=job:(basketball AND mvp)//查询出所有job是basketball并且有mvp的文档
    GET /u/_search?q=job:(basketball NOT mvp)//查询出所有job是basketball并且没有mvp的文档
    GET /u/_search?q=job:(basketball || mvp)//查询出所有job是basketball或者有mvp的文档
    {
        "profile":true"//查看es查询的过程
    }
    
    加减操作

    +:在url写成%2B必须有 must
    -:必须没有 must_not

    GET /u/_search?q=basketball  %2Bmvp//查询出所有是basketball 并且一定包含mvp的文档
    GET /u/_search?q=(basketball  %2Bmvp)//查询出所有是basketball 并且一定包含mvp的文档
    GET /u/_search?q=basketball -2Bmvp//查询出所有是basketball 并且一定不包含mvp的文档
    GET /u/_search?q=job:(basketball -2Bmvp)//查询出所有job是basketball 并且一定不包含mvp的文档
    
    范围查询

    闭区间 [ ] 开区间{ }
    age:[1 TO 10]相当于1<=age<=10
    age:[1 TO 10}相当于1<=age<10
    age:[1 TO ]相当于age>=1
    age:[* TO 10]相当于age<=10

    GET /u/_search?q=basketball AND mvp age:>31 //查询出所有包含basketball 并且同时有mvp 的字段或者age大于31
    GET /u/_search?q=basketball AND mvp AND age:>31//查询出所有包含basketball 并且同时有mvp 的字段并且age大于31
    
    通配符查询

    username:j?mes:匹配任意一个字符
    username:jam*:匹配任意多个字符
    username:j*s:匹配任意多个字符

    GET /u/_search?q=j*s
    GET /u/_search?q=username:j*s
    GET /u/_search?q=j?mes
    

    query DSL 的写法

    post /u/_search
    {
        "query": {
            "wildcard": {
                "username.keyword":"j*s" 
            }
        }
    }
    
    正则表达式查询

    这个需要对正则表达的掌握能力,举两个例子

    GET /u/_search?q=username:/j.{1,}/
    GET /u/_search?q=username:/[张李].*亭{1,}.*/
    

    query DSL 的写法

    post /u/_search
    {
        "query": {
            "regexp": {
                "username":"j.*" 
            }
        }
        
    }
    
    模糊匹配查询
    GET /u/_search?q=job:basketball~1 //查询job中与basketball相差1个char值的文档,例如basketball 、basketball mvp
    
    近似度查询
    GET /u/_search?q=job:“basketball mvp“~1 //匹配到basketball mvp 前后中间可以允许插入1个词 basketball xxxx mvp\basketball mvp xxxx\xxxx basketball mvp都会匹配到,
    

    Request Body Search

    query DSL

    字段查询

    1、全文匹配
    对text类型的字段查询时,会先分词

    • match:
      分词后词语没有先后顺序,随意组合
    select * from u where job like '%basketball%' or job like '%mvp%'
    
    post /u/_search
    {
        "profile":true,//查看es查询的过程
        "query":{
            "match":{
                "job":"basketball mvp"//job字段查询即包含basketball 或者包含mvp的文档
            }
        }
    }
    
    select * from u where job like '%basketball%' and job like '%mvp%'
    
    post /u/_search
    {
        "query": {
            "match":{
                "job":{
                    "query":"basketball mvp",//job必须同时包含basketball和mvp
                    "operator":"and"//默认是or
                }
            }
        }
    }
    
    post /u/_search
    {
        "query": {
            "match":{
                "job":{
                    "query":"basketball mvp act",
                    "minimum_should_match":"2"//搜索出job字段中至少包含关键词其中两个才会匹配上
                }
                
            }
        }
    }
    
    • match_all:
    select * from u
    
    post /u/_search
    {
      "query": {
        "match_all": {}
      }
    }
    
    • match_phrase:
      分词后词语存在先后顺序
      1. match_phrase还是分词后去搜的
      2. 目标文档需要包含分词后的所有词
      3. 目标文档还要保持这些词的相对顺序和文档中的一致
    post /u/_search
    {
        "query": {
            "match_phrase":{
                "job":"basketball mvp"//查询包含basketball mvp的文档,
    //与term不同的是term是从索引的单词找,match_phrase从文档的单词找
            }
        }
    }
    
    post /u/_search
    {
        "query": {
            "match_phrase":{
                "job":{
                    "query":"basketball act",
                    "slop":"1"//允许文档出现和搜索条件相差一个距离的文档
           // 例如这里会匹配到 basketball xxxx act/basketball act xxxx/xxxx basketball act
                }
            }
        }
    }
    
    • query_string:
      指定字段查询,类似q
    post /u/_search
    {
        "query": {
            "query_string":{
                    "default_field":"job",//匹配job字段中即有basketball又有act的文档
                "query":"basketball AND act"
            }
        }
    }
    
    post /u/_search
    {
        "query": {
            "query_string":{
                    "fields":["job","username"],//只匹配job和username字段
                    "query":"james act"
            }
        }
    }
    

    2、精确查询

    • term、terms:将查询语句作为一个单词查询,不做分词处理。
      term和match_phrase有点像,但是又有很大的区别,term性能比match_phrase好很多倍
    select * from u where job="basketball mvp"
    
    post /u/_search
    {
        "query": {
            "term":{
                "job.keyword":"basketball mvp"//这里在倒排索引中匹配basketball mvp
    //最终的结果是匹配不到任何文档,因为索引中都是一个个被切分了的单词不存在“basketball mvp”
            }
        }
    }
    
    select * from u where job in ('basketball', 'mvp')
    
    post /u/_search
    {
        "query": {
            "terms":{
                "job.keyword":["basketball","mvp"]
            }
        }
    }
    

    3、范围、排序、分页

    • range: 范围查询 lt:小于、lte:小于等于、gt:大于、gte大于等于
    select * from u where age between 30 and 40;
    
    post /u/_search
    {
      "query" : {  
        "range" : {
          "age" : { 
            "gte" : 30,
            "lte" : 40
          }
        }
      }
    }
    
    • sort,from,size:
    POST /test/product/_search
    {
      "query":{
        "match": {
          "productName":"苹果小米华为"
        }
        
      },
      "sort":{"price":"desc"},
      "from":2,
      "size":3
    }
    

    scroll:深分页,对于上面介绍的浅分页,如果请求的页数较少(假设每页20个docs), Elasticsearch不会有什么问题,但是如果页数较大时,比如请求第1000页,Elasticsearch不得不取出第1页到第1000页的所有docs,再去除第1页到第999页的docs,得到第1000页的docs。解决的方式就是使用scroll,scroll就是维护了当前索引段的一份快照信息--缓存

    初始化的时候就像是普通的search一样 其中的scroll=3m代表当前查询的数据缓存3分钟

    POST test/_search?scroll=3m
    {
      "query":{
        "match_all": {}
      }
    }
    

    在遍历时候,拿到上一次遍历中的_scroll_id,然后带scroll参数,3m代表重置过期时间

    POST /_search/scroll
    {
      "scroll" : "3m",
      "scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFjlxTWE1RTZwUmdpd3FZSkpsYm5kYXcAAAAAAAA-vxZBRWtUWDAyalM5YTZvbmx0YTJxQjZR"
    }
    
    相关性得分(_score)

    依据:

    • 词频:单词在该文档出现的频率越高,相关性越高
    • 文档长度:文档越短,相关性越高
    • 包含单词文档数量:文档包含某个单词的数量越少,相关性越高

    复合查询

    constant_score:

    将其查询结果的文档得分都设置为1或者boost的值,这个是在当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时使用

    POST /test/product/_search
    {
      "query":{
        "constant_score": {
          "filter": {
            "match":{
              "productName":"华为"
            }
          },
          "boost": 1
        }
      }
    }
    
    post /u/_search
    {   
        "query": {
            "constant_score":{
                "filter":{
                    "match":{
                        "job":{
                            "query":"basketball mvp",
                            "operator":"and"
                        }
                    }
                }
            }
        }
    }
    

    bool:

    • filter:使用filter查询时会有缓存,所以其效率很高,如果不使用相关性得分的排排序,推荐使用filter
     post /u/_search
    {
        "query": {
            "bool": {
                "filter": {
                    "term": {
                        "job.keyword": "basketball"
                    }
                }
            }
        }
    }
    
     post /u/_search
    {
        "query": {
            "bool": {
                "filter": [
                    {
                        "term": {
                            "job": "basketball"
                        }
                    },
                    {
                        "match": {
                            "job": "act"
                        }
                    }
                ]
            }
        }
    }
    
    • must:
     post /u/_search
    //查询文档中的job字段必须同时包含basketball和act
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "term": {
                            "job": "basketball"
                        }
                    },
                    {
                        
                        "match": {
                            "job": "act"
                        }
                    }
                ]
            }
        }
    }
    
    • must_not:
     post /u/_search
    //查询文档中的job字段必须同时包含basketball和act,而要求必须不能有mvp
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "term": {
                            "job": "basketball"
                        }
                    },
                    {
                        "match": {
                            "job": "act"
                        }
                    }
                ],
                "must_not": [
                    {
                        "match": {
                            "job": "mvp"
                        }
                    }
                ]
            }
        }
    }
    
    • should:默认至少满足一个条件,可以通过minimum_should_match控制满足个数
     post /u/_search
    //查询满足其中之一的查询即可,也就是job中包含basketball或者act或者mvp其中一个就能查询出来
    {
        "query": {
            "bool": {
                "should": [
                    {
                        "term": {
                            "job": "basketball"
                        }
                    },
                    {
                        "match": {
                            "job": "act"
                        }
                    },
                    {
                        "match_phrase": {
                            "job": "basketball mvp"
                        }
                    }
                ]
            }
        }
    }
    
     post /u/_search
    {
        "query": {
            "bool": {
                "should": [
                    {
                        "term": {
                            "job": "basketball"
                        }
                    },
                    {
                        "match": {
                            "job": "act"
                        }
                    },
                    {
                        "match_phrase": {
                            "job": "basketball mvp"
                        }
                    }
                ],
     "minimum_should_match":3//设置了满足条件为3
    //查询结果同时满足其中三个也就job中包含basketball并且包含act和mvp就能查询出来都
            }
        }
    }
    
    • should与must\must_not:查询时必须满足或者必须不满足must/must_not,可以不满足should,如果可以满足should也一并查出
     post /u/_search
    {
        "query": {
            "bool": {
                "should": [
                    {
                        "match": {
                            "job": "act"
                        }
                    }
                ],
                "must": [
                    {
                        "match":{
                            "job":"mvp"
                        }
                    }
                ]
            }
        }
    }
    
    • source:只希望返回个别字段即可
    //只希望查询时返回username字段
    GET /u/_search?_source=username
    

    Count API

    获取符合查询条件的文档数量
    查询语句和上面的一样只是把URL修改了

    post /u/_count
    {
        "query": {
            "bool": {
                "should": [
                    {
                        "match": {
                            "job": "act"
                        }
                    }
                ],
                "must": [
                    {
                        "match":{
                            "job":"mvp"
                        }
                    }
                ]
            }
        }
    }
    

    排序、分页滚动

    sort

    • 数字类型排序遍历
      单字段排序
     post /u/_search
    {
        "query": {
            "bool": {
                "should": [
                    {
                        "match": {
                            "job": "act"
                        }
                    }
                ],
                "must": [
                    {
                        "match": {
                            "job": "mvp"
                        }
                    }
                ]
            }
        },
        "sort": {
            "age": "desc"//按照年龄倒叙排序
        }
    }
    

    多字段排序

     post /u/_search
    {
        "query": {
            "match": {
                "job": "basketball"
            }
        },
        "sort": [
            {
                "age": "desc"
            },
            {
                "_score": "desc"
            }
        ]
    }
    
    • 字符串类型排序
      按照字符串类型排序时不能排序text类型的,只能排序keyword的类型,所以在排序text类型时可以使用text.keyword的方式或者使用设置fielddata的属性,例如如下面的查询
    post /u/_search
    //text.keyword的方式
    {
        "query": {
            "match": {
                "job": "basketball"
            }
        },
        "sort": {
            "username.keyword":"asc"
        }
    }
    

    设置fielddata为true

    post /u/_mapping
    {
       "properties":{
        "job":{
            "type":"text",
            "fielddata": true
        }
       }
    }
    

    然后直接进行text排序

    POST /u/_search
    {
        "query": {
            "match": {
                "job": "basketball"
            }
        },
        "sort": {
            "job":"asc"
        }
    }
    
    • 分页
      from:开始位置 es默认不超过过
      size:获取的总数
      es默认不支持深分页换种说法就是es不支持大容量的分页,默认from+size不能超过10000
    post /u/_search
    {
       "from":9996,
       "size":4//from或者size再设置大一点就会报错
    }
    
    • Scroll 分页滚动、遍历
      利用Scroll可以改变分页查询中不能做深分页的缺点,Scroll查询方式的原理就是通过每次查询后,返回一个scroll_id。根据这个scroll_id 进行下一页的查询。可以把这个scroll_id理解为通常关系型数据库中的游标。scroll查询的数据是当前索引段的一份快照信息–缓存,所以scroll没有实时性
    //创建一个scroll设置,并且设置存活时间是两分钟,也就是快照存活2分钟
    GET /u/_search?scroll=2m    
    {
      "query": {"match_all": {}},
       "size": 1//设置每次滚动取1条数据,结果会返回
    }
    
    image.png

    拿着scroll_id可以进行滚动

    //滚动scroll
    POST /_search?scroll
    {
        "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAANAWb1IxVjQ0cFBUMy1jb1dFZUdRbDNKdw==",
        "scroll":"5m"
    }
    
    • Search After分页滚动、遍历
      利用Search After可以解决Scroll不能实时滚动的缺点,但是Search After只能往下滚动,只支持向下滚动,不支持向上滚动,并且创建Search After必须要给文档排序
    post /u/_search
    {
        "size":1,
       "sort":{
        "age":"desc"
       }
    }
    
    image.png

    将返回结果的sort中的值设置到滚动语句中,上图是56,设置search_after为56

    GET /u/_search
    {
        "size":1,
        "search_after":[56],
       "sort":{
        "age":"desc"
       }
    }
    

    总结分页的使用场景


    Aggregation 聚合查询

    多用于统计使用的,举个例子
    例如统计从事各类职业的人数有多少

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

    返回结果

        "aggregations": {
            "tj": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 2,
                "buckets": [
                    {
                        "key": "act",
                        "doc_count": 2
                    },
                    {
                        "key": "act av",
                        "doc_count": 2
                    },
                    {
                        "key": "basketball",
                        "doc_count": 2
                    },
                    {
                        "key": "basketball mvp",
                        "doc_count": 2
                    },
                    {
                        "key": "basketball mvp act",
                        "doc_count": 2
                    },
                    {
                        "key": "basketball act",
                        "doc_count": 1
                    },
                    {
                        "key": "cartoonman hai",
                        "doc_count": 1
                    },
                    {
                        "key": "cartoonman hot",
                        "doc_count": 1
                    },
                    {
                        "key": "cartoonman qun",
                        "doc_count": 1
                    },
                    {
                        "key": "cartoonman seven",
                        "doc_count": 1
                    }
                ]
            }
        }
    
    

    聚合查询做的就是类似上面的事情,聚合查询分为4大类分别为:

    • Bucket:分析统计类型,类似数据库的group by
    • Metric:指标类型,统计如最大值,最小值,平均值等
    • Pipeline:管道分析类型,基于上一级分析的结果进行再次分析
    • Matrix:矩阵分析类型,是es的多维度分析

    Bucket

    bucket的作用类似数据库的分组,把不同的分析结果装到几个桶里

    • terms:按照词语分桶,分桶字段如果是keyword不会进行分词,直接按照整个单词分桶,如果是text则会先分词在分桶,不过使用text进行聚合需要设置fielddata为true
    GET /u/_search
    {
        "aggs": {
            "aggs_bulk": {
                "terms": {
                    "field": "job.keyword",
                    "size":3//指定返回的个数
                }
            }
        }
    }
    

    返回结果

     "aggregations": {
            "aggs_bulk": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 11,
                "buckets": [
                    {
                        "key": "act",
                        "doc_count": 2
                    },
                    {
                        "key": "act av",
                        "doc_count": 2
                    },
                    {
                        "key": "basketball",
                        "doc_count": 2
                    }
                ]
            }
        }
    
    • range
      范围聚合,统计数据指定范围的数量
    GET /u/_search
    {
        "aggs": {
            "aggs_range": {
                "range": {
                    "field": "age",
                    "ranges": [
                        {
                            "to": 36//统计年龄小于36的人数
                        },
                        {
                            "from": 35,
                            "to": 41
                        }//统计年龄35.0-41.0之间的人数
                    ]
                }
            }
        }
    }
    

    返回结果

     "aggregations": {
            "aggs_range": {
                "buckets": [
                    {
                        "key": "*-36.0",
                        "to": 36.0,
                        "doc_count": 9
                    },
                    {
                        "key": "35.0-41.0",
                        "from": 35.0,
                        "to": 41.0,
                        "doc_count": 7
                    }
                ]
            }
        }
    
    • date range
      指定日期范围的分桶
    GET /u/_search
    {
        "aggs": {
            "aggs_range": {
                "date_range": {
                    "field": "brith",
                    "format":"yyyy-MM-dd HH:mm:ss",
                    "ranges": [
                        {
                            "from":"1990-01-01 00:00:00",
                            "to": "2000-12-12 12:00:00"
                        }
                    ]
                }
            }
        }
    }
    

    返回结果

    "aggregations": {
            "aggs_range": {
                "buckets": [
                    {
                        "key": "1990-01-01 00:00:00-2000-12-12 12:00:00",
                        "from": 6.31152E11,
                        "from_as_string": "1990-01-01 00:00:00",
                        "to": 9.766224E11,
                        "to_as_string": "2000-12-12 12:00:00",
                        "doc_count": 8
                    }
                ]
            }
        }
    
    • histogram
      统计固定间隔的数据数量。类似一个树形柱状图
    GET /u/_search
    {
        "aggs": {
            "aggs_his": {
                "histogram": {
                    "field": "age",
                    "interval":5,//统计年龄间隔5岁的各个阶段的人数
                    "extended_bounds": //查询范围
                        {
                            "min":30,
                            "max": 56
                        }
                }
            }
        }
    }
    

    返回结果

     "aggregations": {
            "aggs_his": {
                "buckets": [
                    {
                        "key": 25.0,
                        "doc_count": 2
                    },
                    {
                        "key": 30.0,
                        "doc_count": 6
                    },
                    {
                        "key": 35.0,
                        "doc_count": 7
                    },
                    {
                        "key": 40.0,
                        "doc_count": 1
                    },
                    {
                        "key": 45.0,
                        "doc_count": 0
                    },
                    {
                        "key": 50.0,
                        "doc_count": 0
                    },
                    {
                        "key": 55.0,
                        "doc_count": 1
                    }
                ]
            }
        }
    
    • date histogram
      用于日期的histogram
    GET /u/_search
    {
        "aggs": {
            "aggs_his": {
                "date_histogram": {
                    "field": "brith",
                    "interval":"year",//出生日期以每一年为间隔
                    "format": "yyyy-MM-dd HH:mm:ss"
                }
            }
        }
    }
    

    输出结果

    "aggregations": {
            "aggs_his": {
                "buckets": [
                    {
                        "key_as_string": "1954-01-01 00:00:00",
                        "key": -504921600000,
                        "doc_count": 1
                    },
                    {
                        "key_as_string": "1959-01-01 00:00:00",
                        "key": -347155200000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1967-01-01 00:00:00",
                        "key": -94694400000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1968-01-01 00:00:00",
                        "key": -63158400000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1969-01-01 00:00:00",
                        "key": -31536000000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1970-01-01 00:00:00",
                        "key": 0,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1971-01-01 00:00:00",
                        "key": 31536000000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1972-01-01 00:00:00",
                        "key": 63072000000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1973-01-01 00:00:00",
                        "key": 94694400000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1974-01-01 00:00:00",
                        "key": 126230400000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1975-01-01 00:00:00",
                        "key": 157766400000,
                        "doc_count": 1
                    },
                    {
                        "key_as_string": "1976-01-01 00:00:00",
                        "key": 189302400000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1977-01-01 00:00:00",
                        "key": 220924800000,
                        "doc_count": 0
                    },
                    {
                        "key_as_string": "1982-01-01 00:00:00",
                        "key": 378691200000,
                        "doc_count": 1
                    },
                    {
                        "key_as_string": "1983-01-01 00:00:00",
                        "key": 410227200000,
                        "doc_count": 1
                    },
                    {
                        "key_as_string": "1984-01-01 00:00:00",
                        "key": 441763200000,
                        "doc_count": 0
                    },
                  .................
    

    Metric

    - 单值分析

    分析只输出一个结果

    • min、max、avg、sum
    //查询age的最小值
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_name": {
                "min": {
                    "field": "age"
                }
            }
        }
    }
    
    //查询age的最大值
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_name": {
                "max": {
                    "field": "age"
                }
            }
        }
    }
    
    //查询age的总值
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_name": {
                "sum": {
                    "field": "age"
                }
            }
        }
    }
    
    //查询age的平均值
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_name": {
                "avg": {
                    "field": "age"
                }
            }
        }
    }
    

    可以将他们组合在一起

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_avg": {
                "avg": {
                    "field": "age"
                }
            },
            "aggs_sum": {
                "sum": {
                    "field": "age"
                }
            },
            "aggs_max": {
                "max": {
                    "field": "age"
                }
            },
            "aggs_min": {
                "min": {
                    "field": "age"
                }
            }
        }
    }
    
    • cardinality:作用类似数据库的distinct,统计不同的数值个数
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_cardinality": {
                "cardinality": {
                    "field": "job.keyword"//统计工作字段不同的值有多少个
                }
            }
        }
    }
    
    - 多值分析

    分析可以输出多个结果

    • stats、extended_stats、percentiles:
    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_stats": {
                "stats": {
                    "field": "age"
                }
            }
        }
    }
    

    输出的结果

      "aggregations": {
            "aggs_count": {
                "count": 17,
                "min": 25.0,
                "max": 56.0,
                "avg": 34.64705882352941,
                "sum": 589.0
            }
        }
    

    计算方差、标准差等使用extended_stats

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_estats": {
                "extended_stats": {
                    "field": "age"
                }
            }
        }
    }
    

    输出结果

        "aggregations": {
            "aggs_estats": {
                "count": 17,
                "min": 25.0,
                "max": 56.0,
                "avg": 34.64705882352941,
                "sum": 589.0,
                "sum_of_squares": 21175.0,
                "variance": 45.16955017301028,
                "std_deviation": 6.720829574763094,
                "std_deviation_bounds": {
                    "upper": 48.0887179730556,
                    "lower": 21.205399674003225
                }
            }
        }
    

    使用percentiles统计范围,例如统计数据中百分之多少的人是在哪个年龄段

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_percentile": {
                "percentiles": {
                    "field": "age"
                }
            }
        }
    }
    

    返回结果

       "aggregations": {
           "aggs_percentile": {
               "values": {
                   "1.0": 24.999999999999996,//24岁年龄段的有百分之1
                   "5.0": 25.0,//25岁年龄段的有百分之5
                   "25.0": 31.0,//31岁年龄段的有百分之25
                   "50.0": 35.0,//35岁年龄段的有百分之50
                   "75.0": 36.0,//36岁年龄段的有百分之75
                   "95.0": 50.74999999999998,//51岁年龄段的有百分之95
                   "99.0": 56.0//56岁年龄段的有百分之99
               }
           }
    }
    

    我们可以指定某个百分数范围内对应的数值是哪些

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_percentile": {
                "percentiles": {
                    "field": "age",
                    "percents":[50,75]
                }
            }
        }
    }
    

    返回结果

     "aggregations": {
            "aggs_percentile": {
                "values": {
                    "50.0": 35.0,
                    "75.0": 36.0
                }
            }
        }
    

    我们可以指定某个数值范围内是在数据中是处于哪个百分位

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "aggs_percentile": {
                "percentile_ranks": {
                    "field": "age",
                    "values":[56]//查询数据中在56岁范围内的有百分之多少
                }
            }
        }
    }
    

    输出结果

        "aggregations": {
            "aggs_percentile": {
                "values": {
                    "56.0": 100.0//百分之100
                }
            }
        }
    

    我们希望能从分组统计中同时获取到详情可以使用top_hits

    GET /u/_search
    {
        "size": 0,
        "aggs": {
            "tj": {
                "terms": {
                    "field": "job.keyword"
                },
                "aggs": {
                    "my_top": {
                        "top_hits": {
                            "size": 10,
                            "sort": [
                                {
                                    "age": {
                                        "order": "desc"
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
    
    • 桶中桶 bucket+Metric的组合拳

    在分组后,对每个组在进行统计

    GET /u/_search
    //统计在职业分组后,再统计每组职业的年龄段占比多少
    {
        "aggs": {
            "aggs_term": {
                "terms": {
                    "field": "job.keyword",
                    "size": 10
                },
                "aggs": {
                    "aggs_percentile": {
                        "percentiles": {
                            "field": "age"
                        }
                    }
                }
            }
        }
    }
    

    返回结果

    "aggregations": {
            "aggs_term": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 2,
                "buckets": [
                    {
                        "key": "act",
                        "doc_count": 2,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 36.0,
                                "5.0": 36.0,
                                "25.0": 36.0,
                                "50.0": 38.5,
                                "75.0": 41.0,
                                "95.0": 41.0,
                                "99.0": 41.0
                            }
                        }
                    },
                    {
                        "key": "act av",
                        "doc_count": 2,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 25.0,
                                "5.0": 25.0,
                                "25.0": 25.0,
                                "50.0": 30.0,
                                "75.0": 35.0,
                                "95.0": 35.0,
                                "99.0": 35.0
                            }
                        }
                    },
                    {
                        "key": "basketball",
                        "doc_count": 2,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 30.999999999999996,
                                "5.0": 31.0,
                                "25.0": 31.0,
                                "50.0": 31.5,
                                "75.0": 32.0,
                                "95.0": 32.0,
                                "99.0": 32.0
                            }
                        }
                    },
                    {
                        "key": "basketball mvp",
                        "doc_count": 2,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 29.999999999999996,
                                "5.0": 30.0,
                                "25.0": 30.0,
                                "50.0": 31.0,
                                "75.0": 32.0,
                                "95.0": 32.0,
                                "99.0": 32.0
                            }
                        }
                    },
                    {
                        "key": "basketball mvp act",
                        "doc_count": 2,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 30.999999999999996,
                                "5.0": 31.0,
                                "25.0": 31.0,
                                "50.0": 43.5,
                                "75.0": 56.0,
                                "95.0": 56.0,
                                "99.0": 56.0
                            }
                        }
                    },
                    {
                        "key": "basketball act",
                        "doc_count": 1,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 33.0,
                                "5.0": 33.0,
                                "25.0": 33.0,
                                "50.0": 33.0,
                                "75.0": 33.0,
                                "95.0": 33.0,
                                "99.0": 33.0
                            }
                        }
                    },
                    {
                        "key": "cartoonman hai",
                        "doc_count": 1,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 36.0,
                                "5.0": 36.0,
                                "25.0": 36.0,
                                "50.0": 36.0,
                                "75.0": 36.0,
                                "95.0": 36.0,
                                "99.0": 36.0
                            }
                        }
                    },
                    {
                        "key": "cartoonman hot",
                        "doc_count": 1,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 36.0,
                                "5.0": 36.0,
                                "25.0": 36.0,
                                "50.0": 36.0,
                                "75.0": 36.0,
                                "95.0": 36.0,
                                "99.0": 36.0
                            }
                        }
                    },
                    {
                        "key": "cartoonman qun",
                        "doc_count": 1,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 36.0,
                                "5.0": 36.0,
                                "25.0": 36.0,
                                "50.0": 36.0,
                                "75.0": 36.0,
                                "95.0": 36.0,
                                "99.0": 36.0
                            }
                        }
                    },
                    {
                        "key": "cartoonman seven",
                        "doc_count": 1,
                        "aggs_percentile": {
                            "values": {
                                "1.0": 36.0,
                                "5.0": 36.0,
                                "25.0": 36.0,
                                "50.0": 36.0,
                                "75.0": 36.0,
                                "95.0": 36.0,
                                "99.0": 36.0
                            }
                        }
                    }
                ]
            }
    
    • Pipeline管道聚合分析

    针对上层分析的结果进行再次分析,其分析的结果会输出到上层的结果中,根据输出的位置不同分为两类:

    • 内嵌到上层的结果中
      min、max、avg、stats、percentiles
      min_bucket\max_bucket\avg_bucket\stats_bucket\percentiles_bucket
      用法差不多,举一个例子,
    //计算每一类职业的平均收入,然后找出平均收入最低的职业
    GET /u/_search
    {
        "aggs": {
            "aggs_term": {
                "terms": {
                    "field": "job.keyword"
                },
                "aggs": {
                    "aggs_avg": {
                        "avg": {
                            "field": "income"
                        }
                    }
                }
            },
            "min_pipeline": {//给pipeline起名字,pipeline与aggs的子项aggs_term同级,导致后面的buckets_path要写成aggs_term>aggs_avg
    //分析谁就与谁同级
                "min_bucket": {//min_bucket是关键词,如果是算最大值换成max_bucket,平均值换成avg_bucket、同时获取多个指标则用stats_bucket
                    "buckets_path": "aggs_term>aggs_avg"//aggs的所属结构
                }
            }
        }
    }
    

    输出结果

      "min_pipeline": {
                "value": 1000.0,//平均收入最低是1000
                "keys": [//这几个职业都是收入最低的
                    "cartoonman hai",
                    "cartoonman hot",
                    "cartoonman qun",
                    "cartoonman seven"
                ]
            }
    
    • 结果与上层的结果同级

    • 聚合分析的范围

    aggs与query关键字同级,在query执行后,aggs针对query执行的结果进行分析,也就是说query查出来结果就是aggs的分析范围
    也可以在aggs内部使用filter关键词限定范围

    GET /u/_search
    {
        "aggs": {
            "aggs_filter": {
                "filter": {//利用filter限定aggs范围
                    "match": {
                        "job":"basketball"
                    }
                },
                "aggs":{
                    "job_aggs":{
                        "terms":{
                            "field":"job.keyword"
                        }
                    }
                }
            }
           
        }
    }
    

    还要一种限定范围的方法是post_filter在aggs分析之后在进行筛选

    {
        "aggs": {
            "job_aggs": {
                "terms": {
                    "field": "job.keyword"
                }
            }
        },
        "post_filter":{
            "match":{
                "job.keyword":"mvp"
            }
        }
    }
    

    聚合排序sort

    GET /u/_search
    {
        "aggs": {
            "aggs_term": {
                "terms": {
                    "field": "job.keyword",
                     "order":{
                        "aggs_avg":"desc"//以子聚合分析的结果排序
                    }  
                },
                "aggs": {
                    "aggs_avg": {
                        "avg": {
                            "field": "income"
                        }
                    }
                }
                
            }
           
        }
    }
    

    返回结果

     "buckets": [
                    {
                        "key": "soccerball mvp",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 5.0E8
                        }
                    },
                    {
                        "key": "basketball mvp",
                        "doc_count": 2,
                        "aggs_avg": {
                            "value": 1.3E8
                        }
                    },
                    {
                        "key": "basketball",
                        "doc_count": 2,
                        "aggs_avg": {
                            "value": 8.5E7
                        }
                    },
                    {
                        "key": "act",
                        "doc_count": 2,
                        "aggs_avg": {
                            "value": 1.01E7
                        }
                    },
                    {
                        "key": "basketball mvp act",
                        "doc_count": 2,
                        "aggs_avg": {
                            "value": 750000.0
                        }
                    },
                    {
                        "key": "basketball act",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 600000.0
                        }
                    },
                    {
                        "key": "act av",
                        "doc_count": 2,
                        "aggs_avg": {
                            "value": 40000.0
                        }
                    },
                    {
                        "key": "great",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 8000.0
                        }
                    },
                      .........................
    

    以外层的key或者聚合分析数排序

    GET /u/_search
    {
        "aggs": {
            "aggs_term": {
                "terms": {
                    "field": "job.keyword",
                    "order": [
                        {
                            "_key": "desc"//聚合结果的key排序
                        },
                        {
                            "_count": "desc"//聚合数量排序
                        }
                    ]
                },
                "aggs": {
                    "aggs_avg": {
                        "avg": {
                            "field": "income"
                        }
                    }
                }   
            }  
        }
    }
    

    返回结果

    "buckets": [
                    {
                        "key": "soccerball mvp",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 5.0E8
                        }
                    },
                    {
                        "key": "great",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 8000.0
                        }
                    },
                    {
                        "key": "cartoonman seven",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 1000.0
                        }
                    },
                    {
                        "key": "cartoonman qun",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 1000.0
                        }
                    },
                    {
                        "key": "cartoonman hot",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 1000.0
                        }
                    },
                    {
                        "key": "cartoonman hai",
                        "doc_count": 1,
                        "aggs_avg": {
                            "value": 1000.0
                        }
                    },
                      ..........................
    

    相关文章

      网友评论

          本文标题:Elasticsearch学习(一)

          本文链接:https://www.haomeiwen.com/subject/pukaohtx.html