Elasticsearch深入9

bucket与metric两个核心概念

两个核心概念:bucket和metric

bucket:一个数据分组

city name

北京 小李
北京 小王
上海 小张
上海 小丽
上海 小陈

基于city划分buckets

划分出来两个bucket,一个是北京bucket,一个是上海bucket

北京bucket:包含了2个人,小李,小王
上海bucket:包含了3个人,小张,小丽,小陈

按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中

有一些mysql的sql知识的话,聚合,首先第一步就是分组,对每个组内的数据进行聚合分析,分组,就是我们的bucket

metric:对一个数据分组执行的统计

当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量,或者计算一个bucket内所有数据的平均值,最大值,最小值

metric,就是对一个bucket执行的某种聚合分析的操作,比如说求平均值,求最大值,求最小值

select count(*)
from access_log
group by user_id

bucket:group by user_id --> 那些user_id相同的数据,就会被划分到一个bucket中
metric:count(*),对每个user_id bucket中所有的数据,计算一个数量

hitogram按价格区间统计电视销量和销售额

histogram:类似于terms,也是进行bucket分组操作,接收一个field,按照这个field的值的各个范围区间,进行bucket分组操作

"histogram":{
"field": "price",
"interval": 2000
},

interval:2000,划分范围,0~2000,2000~4000,4000~6000,6000~8000,8000~10000,buckets

去根据price的值,比如2500,看落在哪个区间内,比如2000~4000,此时就会将这条数据放入2000~4000对应的那个bucket中

bucket划分的方法,terms,将field值相同的数据划分到一个bucket中

bucket有了之后,一样的,去对每个bucket执行avg,count,sum,max,min,等各种metric操作,聚合分析

{
    "size":0,
    "aggs":{
        "price":{
            "histogram":{
                "field":"price",
                "interval":2000
            },
            "aggs":{
                "revenue":{
                    "sum":{
                        "field":"price"
                    }
                }
            }
        }
    }
}

bucket,分组操作,histogram,按照某个值指定的interval,划分一个一个的bucket

date histogram,按照我们指定的某个date类型的日期field,以及日期interval,按照一定的日期间隔,去划分bucket

date interval = 1m,

2017-01-01~2017-01-31,就是一个bucket
2017-02-01~2017-02-28,就是一个bucket

然后会去扫描每个数据的date field,判断date落在哪个bucket中,就将其放入那个bucket

2017-01-05,就将其放入2017-01-01~2017-01-31,就是一个bucket

min_doc_count:即使某个日期interval,2017-01-01~2017-01-31中,一条数据都没有,那么这个区间也是要返回的,不然默认是会过滤掉这个区间的
extended_bounds,min,max:划分bucket的时候,会限定在这个起始日期,和截止日期内

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"
                }
            }
        }
    }
}

基于nested object实现博客与评论嵌套关系

1、做一个实验,引出来为什么需要nested object

 冗余数据方式的来建模,其实用的就是object类型,我们这里又要引入一种新的object类型,nested object类型

 博客,评论,做的这种数据模型

 PUT /website/blogs/6

{

  "title": "花无缺发表的一篇帖子",

  "content":  "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",

  "tags":  [ "投资", "理财" ],

  "comments": [

    {

      "name":    "小鱼儿",

      "comment": "什么股票啊?推荐一下呗",

      "age":     28,

      "stars":   4,

      "date":    "2016-09-01"

    },

    {

      "name":    "黄药师",

      "comment": "我喜欢投资房产,风,险大收益也大",

      "age":     31,

      "stars":   5,

      "date":    "2016-10-22"

    }

  ]

}

被年龄是28岁的黄药师评论过的博客,搜索

GET /website/blogs/_search

{

  "query": {

    "bool": {

      "must": [

        { "match": { "comments.name": "黄药师" }},

        { "match": { "comments.age":  28      }}

      ]

    }

  }

}

{

  "took": 102,

  "timed_out": false,

  "_shards": {

    "total": 5,

    "successful": 5,

    "failed": 0

  },

  "hits": {

    "total": 1,

    "max_score": 1.8022683,

    "hits": [

      {

        "_index": "website",

        "_type": "blogs",

        "_id": "6",

        "_score": 1.8022683,

        "_source": {

          "title": "花无缺发表的一篇帖子",

          "content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",

          "tags": [

            "投资",

            "理财"

          ],

          "comments": [

            {

              "name": "小鱼儿",

              "comment": "什么股票啊?推荐一下呗",

              "age": 28,

              "stars": 4,

              "date": "2016-09-01"

            },

            {

              "name": "黄药师",

              "comment": "我喜欢投资房产,风,险大收益也大",

              "age": 31,

              "stars": 5,

              "date": "2016-10-22"

            }

          ]

        }

      }

    ]

  }

}

结果是。。。好像不太对啊???

object类型数据结构的底层存储。。。

 {

  "title":            [ "花无缺", "发表", "一篇", "帖子" ],

  "content":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],

  "tags":             [ "投资", "理财" ],

  "comments.name":    [ "小鱼儿", "黄药师" ],

  "comments.comment": [ "什么", "股票", "推荐", "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],

  "comments.age":     [ 28, 31 ],

  "comments.stars":   [ 4, 5 ],

  "comments.date":    [ 2016-09-01, 2016-10-22 ]

}

object类型底层数据结构,会将一个json数组中的数据,进行扁平化

 所以,直接命中了这个document,name=黄药师,age=28,正好符合

 2、引入nested object类型,来解决object类型底层数据结构导致的问题

 修改mapping,将comments的类型从object设置为nested

 PUT /website

{

  "mappings": {

    "blogs": {

      "properties": {

        "comments": {

          "type": "nested",

          "properties": {

            "name":    { "type": "string"  },

            "comment": { "type": "string"  },

            "age":     { "type": "short"   },

            "stars":   { "type": "short"   },

            "date":    { "type": "date"    }

          }

        }

      }

    }

  }

}

{

  "comments.name":    [ "小鱼儿" ],

  "comments.comment": [ "什么", "股票", "推荐" ],

  "comments.age":     [ 28 ],

  "comments.stars":   [ 4 ],

  "comments.date":    [ 2014-09-01 ]

}

{

  "comments.name":    [ "黄药师" ],

  "comments.comment": [ "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],

  "comments.age":     [ 31 ],

  "comments.stars":   [ 5 ],

  "comments.date":    [ 2014-10-22 ]

}

{

  "title":            [ "花无缺", "发表", "一篇", "帖子" ],

  "body":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],

  "tags":             [ "投资", "理财" ]

}

再次搜索,成功了。。。

 GET /website/blogs/_search

{

  "query": {

    "bool": {

      "must": [

        {

          "match": {

            "title": "花无缺"

          }

        },

        {

          "nested": {

            "path": "comments",

            "query": {

              "bool": {

                "must": [

                  {

                    "match": {

                      "comments.name": "黄药师"

                    }

                  },

                  {

                    "match": {

                      "comments.age": 28

                    }

                  }

                ]

              }

            }

          }

        }

      ]

    }

  }

}

score_mode:max,min,avg,none,默认是avg

 如果搜索命中了多个nested document,如何讲个多个nested document的分数合并为一个分数

聚合数据分析的需求1:按照评论日期进行bucket划分,然后拿到每个月的评论的评分的平均值

 GET /website/blogs/_search

{

  "size": 0,

  "aggs": {

    "comments_path": {

      "nested": {

        "path": "comments"

      },

      "aggs": {

        "group_by_comments_date": {

          "date_histogram": {

            "field": "comments.date",

            "interval": "month",

            "format": "yyyy-MM"

          },

          "aggs": {

            "avg_stars": {

              "avg": {

                "field": "comments.stars"

              }

            }

          }

        }

      }

    }

  }

}

聚合数据分析的需求2:按发表人年龄划分tags的统计

GET /website/blogs/_search

{

  "size": 0,

  "aggs": {

    "comments_path": {

      "nested": {

        "path": "comments"

      },

      "aggs": {

        "group_by_comments_age": {

          "histogram": {

            "field": "comments.age",

            "interval": 10

          },

          "aggs": {

            "reverse_path": {

              "reverse_nested": {},//可以使用comments外的filed今天聚合操作

              "aggs": {

                "group_by_tags": {

                  "terms": {

                    "field": "tags.keyword"

                  }

                }

              }

            }

          }

        }

      }

    }

  }

}

原文地址:https://www.cnblogs.com/jiahaoJAVA/p/11058403.html