美文网首页
es使用与原理5 -- 中文分词及热更新词库,聚合分析等等

es使用与原理5 -- 中文分词及热更新词库,聚合分析等等

作者: Teemo_fca4 | 来源:发表于2020-03-20 16:16 被阅读0次

    中国人很喜欢吃油条的中英文分词器两种分法

    standard:中 国 人 很 喜 欢 吃 油 条
    ik:中国人 很 喜欢 吃 油条

    1、在elasticsearch中安装ik中文分词器

    (1)git clone https://github.com/medcl/elasticsearch-analysis-ik
    (2)git checkout tags/v5.2.0
    (3)mvn package
    (4)将target/releases/elasticsearch-analysis-ik-5.2.0.zip拷贝到es/plugins/ik目录下
    (5)在es/plugins/ik下对elasticsearch-analysis-ik-5.2.0.zip进行解压缩
    (6)重启es
    2、ik分词器的两种分词策略(一般使用 ik_max_word策略)
    ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;

    ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。

    
    PUT /my_index 
    {
      "mappings": {
        "my_type": {
          "properties": {
            "text": {
              "type": "text",
              "analyzer": "ik_max_word"
            }
          }
        }
      }
    }
    
    POST /my_index/my_type/_bulk
    { "index": { "_id": "1"} }
    { "text": "男子偷上万元发红包求交女友 被抓获时仍然单身" }
    { "index": { "_id": "2"} }
    { "text": "16岁少女为结婚“变”22岁 7年后想离婚被法院拒绝" }
    { "index": { "_id": "3"} }
    { "text": "深圳女孩骑车逆行撞奔驰 遭索赔被吓哭(图)" }
    { "index": { "_id": "4"} }
    { "text": "女人对护肤品比对男票好?网友神怼" }
    { "index": { "_id": "5"} }
    { "text": "为什么国内的街道招牌用的都是红黄配?" }
    
    GET /my_index/_analyze
    {
      "text": "男子偷上万元发红包求交女友 被抓获时仍然单身",
      "analyzer": "ik_max_word"
    }
    
    GET /my_index/my_type/_search 
    {
      "query": {
        "match": {
          "text": "16岁少女结婚好还是单身好?"
        }
      }
    }
    
    IK分词器配置文件及自定义词库

    1、ik配置文件

    ik配置文件地址:es/plugins/ik/config目录

    IKAnalyzer.cfg.xml:用来配置自定义词库
    main.dic:ik原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起
    quantifier.dic:放了一些单位相关的词
    suffix.dic:放了一些后缀
    surname.dic:中国的姓氏
    stopword.dic:英文停用词

    ik原生最重要的两个配置文件

    main.dic:包含了原生的中文词语,会按照这个里面的词语去分词
    stopword.dic:包含了英文的停用词
    停用词,stopword

    a the and at but ,一般,像停用词,会在分词的时候,直接被干掉,不会建立在倒排索引中
    2、自定义词库

    (1)自己建立词库:每年都会涌现一些特殊的流行词,网红,蓝瘦香菇,喊麦,鬼畜,一般不会在ik的原生词典里

    自己补充自己的最新的词语,到ik的词库里面去

    IKAnalyzer.cfg.xml:ext_dict,custom/mydict.dic

    补充自己的词语,然后需要重启es,才能生效

    (2)自己建立停用词库:比如了,的,啥,么,我们可能并不想去建立索引,让人家搜索

    custom/ext_stopword.dic,已经有了常用的中文停用词,可以补充自己的停用词,然后重启es

    修改IK分词器源码来基于mysql热更新词库

    每次都是在es的扩展词典中,手动添加新词语,很坑
    (1)每次添加完,都要重启es才能生效,非常麻烦
    (2)es是分布式的,可能有数百个节点,你不能每次都一个一个节点上面去修改

    es不停机,直接我们在外部某个地方添加新的词语,es中立即热加载到这些新词语

    两种热更新的方案
    (1)修改ik分词器源码,然后手动支持从mysql中每隔一定时间,自动加载新的词库
    (2)基于ik分词器原生支持的热更新方案,部署一个web服务器,提供一个http接口,通过modified和tag两个http响应头,来提供词语的热更新

    一般都用第一种方案,第二种 ik git社区官方都不建议采用,觉得不太稳定

    2、修改源码

    Dictionary类,169行:Dictionary单例类的初始化方法,在这里需要创建一个我们自定义的线程,并且启动它 new Thread(new HotDictReloadThread()).start();
    HotDictReloadThread类:就是死循环,不断调用Dictionary.getSingleton().reLoadMainDict(),去重新加载词典 loadMainDict
    Dictionary类,389行:this.loadMySQLExtDict();
    Dictionary类,683行:this.loadMySQLStopwordDict();

    3、mvn package打包代码

    target\releases\elasticsearch-analysis-ik-5.2.0.zip

    4、解压缩ik压缩包

    将mysql驱动jar,放入ik的目录下

    5、修改jdbc相关配置

    6、重启es

    观察日志,日志中就会显示我们打印的那些东西,比如加载了什么配置,加载了什么词语,什么停用词

    7、在mysql中添加词库与停用词

    8、分词实验,验证热更新生效

    聚合分析之bucket和metric

    bucket:按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中。如:
    北京 小李
    北京 小王
    上海 小张
    上海 小丽
    上海 小陈
    基于city划分buckets 划分出来两个bucket,一个是北京bucket,一个是上海bucket
    北京bucket:包含了2个人,小李,小王
    上海bucket:包含了3个人,小张,小丽,小陈
    metric:对一个数据分组执行的统计。当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量,或者计算一个bucket内所有数据的平均值,最大值,最小值
    聚合统计--哪种颜色电视销量最高

    PUT /tvs
    {
        "mappings": {
            "sales": {
                "properties": {
                    "price": {
                        "type": "long"
                    },
                    "color": {
                        "type": "keyword"
                    },
                    "brand": {
                        "type": "keyword"
                    },
                    "sold_date": {
                        "type": "date"
                    }
                }
            }
        }
    }
    
    POST /tvs/sales/_bulk
    { "index": {}}
    { "price" : 1000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-10-28" }
    { "index": {}}
    { "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-11-05" }
    { "index": {}}
    { "price" : 3000, "color" : "绿色", "brand" : "小米", "sold_date" : "2016-05-18" }
    { "index": {}}
    { "price" : 1500, "color" : "蓝色", "brand" : "TCL", "sold_date" : "2016-07-02" }
    { "index": {}}
    { "price" : 1200, "color" : "绿色", "brand" : "TCL", "sold_date" : "2016-08-19" }
    { "index": {}}
    { "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-11-05" }
    { "index": {}}
    { "price" : 8000, "color" : "红色", "brand" : "三星", "sold_date" : "2017-01-01" }
    { "index": {}}
    { "price" : 2500, "color" : "蓝色", "brand" : "小米", "sold_date" : "2017-02-12" }
    

    2、统计哪种颜色的电视销量最高

    GET /tvs/sales/_search
    {
        "size" : 0,
        "aggs" : { 
            "popular_colors" : { 
                "terms" : { 
                  "field" : "color"
                }
            }
        }
    }
    
    # 请求参数解释
    size:只获取聚合结果,而不要执行聚合的原始数据
    aggs:固定语法,要对一份数据执行分组聚合操作
    popular_colors:就是对每个aggs,都要起一个名字,这个名字是随机的,你随便取什么都ok
    terms:根据字段的值进行分组
    field:根据指定的字段的值进行分组
    
    //返回结果
    {
      "took": 22,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "popular_colors": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "红色",
              "doc_count": 4
            },
            {
              "key": "绿色",
              "doc_count": 2
            },
            {
              "key": "蓝色",
              "doc_count": 2
            }
          ]
        }
      }
    }
    # 返回数据解释:
    hits.hits:我们指定了size是0,所以hits.hits就是空的,否则会把执行聚合的那些原始数据给你返回回来
    aggregations:聚合结果
    popular_color:我们指定的某个聚合的名称
    buckets:根据我们指定的field划分出的buckets
    key:每个bucket对应的那个值
    doc_count:这个bucket分组内,有多少个数据
    数量,其实就是这种颜色的销量
    
    默认的排序规则:按照doc_count降序排序
    

    聚合统计--bucket+metric:统计每种颜色电视平均价格
    在之前的terms同级下,新增一个aggs分组之后,聚合求平均

    GET /tvs/sales/_search
    {
       "size" : 0,
       "aggs": {
          "colors": {
             "terms": {
                "field": "color"
             },
             "aggs": { 
                "avg_price": { 
                   "avg": {
                      "field": "price" 
                   }
                }
             }
          }
       }
    }
    
    # 返回数据
    {
      "took": 14,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "colors": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "红色",
              "doc_count": 4,
              "avg_price": {
                "value": 3250
              }
            },
            {
              "key": "绿色",
              "doc_count": 2,
              "avg_price": {
                "value": 2100
              }
            },
            {
              "key": "蓝色",
              "doc_count": 2,
              "avg_price": {
                "value": 2000
              }
            }
          ]
        }
      }
    }
    # 返回数据解释
    buckets,除了key和doc_count
    avg_price:我们自己取的metric aggs的名字
    value:我们的metric计算的结果,每个bucket中的数据的price字段求平均值后的结果
    
    select avg(price) from tvs.sales group by color
    

    bucket嵌套实现颜色+品牌的多层下钻分析
    比如说,现在红色的电视有4台,同时这4台电视中,有3台是属于长虹的,1台是属于小米的
    红色电视中的3台长虹的平均价格是多少?
    红色电视中的1台小米的平均价格是多少?

    下钻的意思是,已经分了一个组了,比如说颜色的分组,然后还要继续对这个分组内的数据,再分组,比如一个颜色内,还可以分成多个不同的品牌的组,最后对每个最小粒度的分组执行聚合分析操作,这就叫做下钻分析

    GET /tvs/sales/_search
    {
      "size": 0,
      "aggs": { 
          "颜色分组":{
            "terms": {
              "field": "color" 
            },
            "aggs": {
              "颜色求平均": {
                "avg": {
                  "field": "price"
                }
              },
              "品牌分组":{
                "terms": {
                  "field": "brand"
                },
                "aggs": {
                  "品牌求平均": {
                    "avg": {
                      "field": "price"
                    }
                  }
                }
              }
            }
          }
      }
    }
    
    //返回数据
    {
      "took": 2,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "颜色分组": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "红色",
              "doc_count": 4,
              "品牌分组": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "长虹",
                    "doc_count": 3,
                    "品牌求平均": {
                      "value": 1666.6666666666667
                    }
                  },
                  {
                    "key": "三星",
                    "doc_count": 1,
                    "品牌求平均": {
                      "value": 8000
                    }
                  }
                ]
              },
              "颜色求平均": {
                "value": 3250
              }
            },
            {
              "key": "绿色",
              "doc_count": 2,
              "品牌分组": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "TCL",
                    "doc_count": 1,
                    "品牌求平均": {
                      "value": 1200
                    }
                  },
                  {
                    "key": "小米",
                    "doc_count": 1,
                    "品牌求平均": {
                      "value": 3000
                    }
                  }
                ]
              },
              "颜色求平均": {
                "value": 2100
              }
            },
            {
              "key": "蓝色",
              "doc_count": 2,
              "品牌分组": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "TCL",
                    "doc_count": 1,
                    "品牌求平均": {
                      "value": 1500
                    }
                  },
                  {
                    "key": "小米",
                    "doc_count": 1,
                    "品牌求平均": {
                      "value": 2500
                    }
                  }
                ]
              },
              "颜色求平均": {
                "value": 2000
              }
            }
          ]
        }
      }
    }
    

    metrics:统计每种颜色电视最大最小价格
    之前我们也可以求数量和平均值
    count:bucket,terms,自动就会有一个doc_count,就相当于是count
    avg:avg aggs,求平均值

    现在我们使用更多的metrics操作
    max:求一个bucket内,指定field值最大的那个数据
    min:求一个bucket内,指定field值最小的那个数据
    sum:求一个bucket内,指定field值的总和
    一般来说,90%的常见的数据分析的操作,metric,无非就是count,avg,max,min,sum

    GET /tvs/sales/_search
    {
       "size" : 0,
       "aggs": {
          "colors": {
             "terms": {
                "field": "color"
             },
             "aggs": {
                "avg_price": { "avg": { "field": "price" } },
                "min_price" : { "min": { "field": "price"} }, 
                "max_price" : { "max": { "field": "price"} },
                "sum_price" : { "sum": { "field": "price" } } 
             }
          }
       }
    }
    
    //返回数据
    {
      "took": 5,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "colors": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "红色",
              "doc_count": 4,
              "max_price": {
                "value": 8000
              },
              "min_price": {
                "value": 1000
              },
              "avg_price": {
                "value": 3250
              },
              "sum_price": {
                "value": 13000
              }
            },
            {
              "key": "绿色",
              "doc_count": 2,
              "max_price": {
                "value": 3000
              },
              "min_price": {
                "value": 1200
              },
              "avg_price": {
                "value": 2100
              },
              "sum_price": {
                "value": 4200
              }
            },
            {
              "key": "蓝色",
              "doc_count": 2,
              "max_price": {
                "value": 2500
              },
              "min_price": {
                "value": 1500
              },
              "avg_price": {
                "value": 2000
              },
              "sum_price": {
                "value": 4000
              }
            }
          ]
        }
      }
    }
    

    hitogram按价格区间统计电视销量和销售额
    histogram:类似于terms,也是进行bucket分组操作,接收一个field,按照这个field的值的各个范围区间,进行bucket分组操作
    interval:2000,划分范围,02000,20004000,40006000,60008000,8000~10000,buckets
    去根据price的值,比如2500,看落在哪个区间内,比如20004000,此时就会将这条数据放入20004000对应的那个bucket中
    bucket划分的方法,terms,将field值相同的数据划分到一个bucket中
    bucket有了之后,一样的,去对每个bucket执行avg,count,sum,max,min,等各种metric操作,聚合分析

    以2000位区间段,求各个区间的产品价格总和

    GET /tvs/sales/_search
    {
       "size" : 0,
       "aggs":{
          "price":{
             "histogram":{ 
                "field": "price",
                "interval": 2000
             },
             "aggs":{
                "revenue": {
                   "sum": { 
                     "field" : "price"
                   }
                 }
             }
          }
       }
    }
    
    //返回数据
    {
      "took": 6,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "price": {
          "buckets": [
            {
              "key": 0,
              "doc_count": 3,
              "revenue": {
                "value": 3700
              }
            },
            {
              "key": 2000,
              "doc_count": 4,
              "revenue": {
                "value": 9500
              }
            },
            {
              "key": 4000,
              "doc_count": 0,
              "revenue": {
                "value": 0
              }
            },
            {
              "key": 6000,
              "doc_count": 0,
              "revenue": {
                "value": 0
              }
            },
            {
              "key": 8000,
              "doc_count": 1,
              "revenue": {
                "value": 8000
              }
            }
          ]
        }
      }
    }
    

    日期间隔举例

    GET /tvs/sales/_search
    {
       "size" : 0,
       "aggs": {
          "sales": {
             "date_histogram": {
                "field": "sold_date",
                "interval": "month", 
                "format": "yyyy-MM-dd",
                "min_doc_count" : 0, 
                "extended_bounds" : { 
                    "min" : "2016-01-01",
                    "max" : "2017-12-31"
                }
             }
          }
       }
    }
    # 参数解释
    min_doc_count:即使某个日期interval,2017-01-01~2017-01-31中,一条数据都没有,那么这个区间也是要返回的,不然默认是会过滤掉这个区间的
    extended_bounds,min,max:划分bucket的时候,会限定在这个起始日期,和截止日期内
    
    //返回数据
    {
      "took": 10,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 8,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "sales": {
          "buckets": [
            {
              "key_as_string": "2016-01-01",
              "key": 1451606400000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-02-01",
              "key": 1454284800000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-03-01",
              "key": 1456790400000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-04-01",
              "key": 1459468800000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-05-01",
              "key": 1462060800000,
              "doc_count": 1
            },
            {
              "key_as_string": "2016-06-01",
              "key": 1464739200000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-07-01",
              "key": 1467331200000,
              "doc_count": 1
            },
            {
              "key_as_string": "2016-08-01",
              "key": 1470009600000,
              "doc_count": 1
            },
            {
              "key_as_string": "2016-09-01",
              "key": 1472688000000,
              "doc_count": 0
            },
            {
              "key_as_string": "2016-10-01",
              "key": 1475280000000,
              "doc_count": 1
            },
            {
              "key_as_string": "2016-11-01",
              "key": 1477958400000,
              "doc_count": 2
            },
            {
              "key_as_string": "2016-12-01",
              "key": 1480550400000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-01-01",
              "key": 1483228800000,
              "doc_count": 1
            },
            {
              "key_as_string": "2017-02-01",
              "key": 1485907200000,
              "doc_count": 1
            },
            {
              "key_as_string": "2017-03-01",
              "key": 1488326400000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-04-01",
              "key": 1491004800000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-05-01",
              "key": 1493596800000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-06-01",
              "key": 1496275200000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-07-01",
              "key": 1498867200000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-08-01",
              "key": 1501545600000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-09-01",
              "key": 1504224000000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-10-01",
              "key": 1506816000000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-11-01",
              "key": 1509494400000,
              "doc_count": 0
            },
            {
              "key_as_string": "2017-12-01",
              "key": 1512086400000,
              "doc_count": 0
            }
          ]
        }
      }
    }
    
    下钻分析之统计每季度每个品牌的销售额

    其实就是先分组再下钻聚合

    GET /tvs/sales/_search 
    {
      "size": 0,
      "aggs": {
        "group_by_sold_date": {
          "date_histogram": {
            "field": "sold_date",
            "interval": "quarter",//quarter是季度的意思,这里是按照季度去划分
            "format": "yyyy-MM-dd",
            "min_doc_count": 0,
            "extended_bounds": {
              "min": "2016-01-01",
              "max": "2017-12-31"
            }
          },
          "aggs": {
            "group_by_brand": { //按照品牌下钻分析
              "terms": {
                "field": "brand"
              },
              "aggs": {
                "sum_price": {
                  "sum": {
                    "field": "price"
                  }
                }
              }
            },
            "total_sum_price": {//每个季度的总销售额
              "sum": {
                "field": "price"
              }
            }
          }
        }
      }
    }
    

    搜索+聚合:统计指定品牌下每个颜色的销量
    其实就是搜索和聚合操作相结合

    GET /tvs/sales/_search 
    {
      "size": 0,
      "query": {
        "term": {
          "brand": {
            "value": "小米"
          }
        }
      },
      "aggs": {
        "group_by_color": {
          "terms": {
            "field": "color"
          }
        }
      }
    }
    

    global bucket:单个品牌与所有品牌销量对比
    global:就是global bucket,就是将所有数据纳入聚合的scope,而不管之前的query。
    出来两个结果,一个结果,是基于query搜索结果来聚合的; 一个结果,是对所有数据执行聚合的

    GET /tvs/sales/_search 
    {
      "size": 0, 
      "query": {
        "term": {
          "brand": {
            "value": "长虹"
          }
        }
      },
      "aggs": {
        "single_brand_avg_price": {
          "avg": {
            "field": "price"
          }
        },
        "all": {
          "global": {},
          "aggs": {
            "all_brand_avg_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        }
      }
    }
    
    //返回结果
    {
      "took": 12,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 3,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "all": {
          "doc_count": 8,
          "all_brand_avg_price": {
            "value": 2650
          }
        },
        "single_brand_avg_price": {
          "value": 1666.6666666666667
        }
      }
    }
    

    过滤+聚合:统计价格大于1200的电视平均价格
    先过滤再聚合

    GET /tvs/sales/_search 
    {
      "size": 0,
      "query": {
        "constant_score": {
          "filter": {
            "range": {
              "price": {
                "gte": 1200
              }
            }
          }
        }
      },
      "aggs": {
        "avg_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
    

    bucket filter:一次统计牌品最近N,M天的平均价格

    GET /tvs/sales/_search 
    {
      "size": 0,
      "query": {
        "term": {
          "brand": {
            "value": "长虹"
          }
        }
      },
      "aggs": {
        "recent_150d": {
          "filter": {
            "range": {
              "sold_date": {
                "gte": "now-150d"
              }
            }
          },
          "aggs": {
            "recent_150d_avg_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        },
        "recent_140d": {
          "filter": {
            "range": {
              "sold_date": {
                "gte": "now-140d"
              }
            }
          },
          "aggs": {
            "recent_140d_avg_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        },
        "recent_130d": {
          "filter": {
            "range": {
              "sold_date": {
                "gte": "now-130d"
              }
            }
          },
          "aggs": {
            "recent_130d_avg_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        }
      }
    }
    

    aggs.filter,针对的是聚合去做的

    如果放query里面的filter,是全局的,会对所有的数据都有影响

    但是,如果,比如说,你要统计,长虹电视,最近1个月的平均值; 最近3个月的平均值; 最近6个月的平均值
    我们就可以使用bucket filter:对不同的bucket下的aggs,进行filter
    排序:按每种颜色的平均销售额降序排序
    之前的话,排序,是按照每个bucket的doc_count降序来排的,但是假如说,我们现在统计出来每个颜色的电视的销售额,需要按照销售额降序排序????

    GET /tvs/sales/_search 
    {
      "size": 0,
      "aggs": {
        "group_by_color": {
          "terms": {
            "field": "color",
            "order": {
              "avg_price": "asc"//根据 avg_price来升序排序
            }
          },
          "aggs": {
            "avg_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        }
      }
    }
    

    颜色+品牌下钻分析时按最深层metric进行排序

    GET /tvs/sales/_search 
    {
      "size": 0,
      "aggs": {
        "group_by_color": {
          "terms": {
            "field": "color"
          },
          "aggs": {
            "group_by_brand": {
              "terms": {
                "field": "brand",
                "order": {
                  "avg_price": "desc"//这里是最深层 在这里做排序就好了
                }
              },
              "aggs": {
                "avg_price": {
                  "avg": {
                    "field": "price"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:es使用与原理5 -- 中文分词及热更新词库,聚合分析等等

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