文章目录
- 三、深入 elasticsearch
 - 1.数据聚合
 - (1)聚合的分类
 - (2)DSL 实现 Bucket 聚合
 - (3)DSL 实现 Metrics 聚合
 - (4)RestAPI 实现聚合
 
- 2.自动补全
 - (1)自定义分词器
 - (2)completion suggester 查询
 
- 3.数据同步
 - (1)elasticsearch 与 mysql 之间的数据同步
 
- 4.集群
 - (1)ES 集群的分布式存储
 - (1)ES 集群的分布式查询
 
三、深入 elasticsearch
1.数据聚合
(1)聚合的分类
聚合可以实现对文档数据的统计、分析、运算。聚合常见的有三类:
- 桶( Bucket )聚合:用来对文档做分组 
  
- TermAggregation :按照文档字段值分组
 - Date Histogram :按照日期阶梯分组,例如一周为一组,或者一月为一组
 
 - 度量( Metric )聚合:用以计算一些值,比如:最大值、最小值、平均值等 
  
- Avg :求平均值
 - Max :求最大值
 - Min :求最小值
 - Stats :同时求 max 、 min 、 avg 、 sum 等
 
 - 管道( pipeline )聚合:其它聚合的结果为基础做聚合
 
(2)DSL 实现 Bucket 聚合
- 现在,我们要统计所有数据中的酒店品牌有几种,此时可以根据酒店品牌的名称做聚合。
类型为 term 类型, DSL 示例: 
GET /hotel/_search
{
  "size": 0, 		//设置 size 为 0 ,结果中不包含文档,只包含聚合结果
  "aggs": { 		//定义聚合
  "brandAgg": { 	//给聚合起个名字
  "terms": { 		//聚合的类型,按照品牌值聚合,所以选择 term
  "field": "brand", //参与聚合的字段
  "size": 20 // 希望获取的聚合结果数量
      }
    }
  }
}
 
- 默认情况下, Bucket 聚合会统计 Bucket 内的文档数量,记为 _count ,并且按照 _count 降序排序。
我们可以修改结果排序方式: 
GET /hotel/_search
{
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "order": {
          "_count": "asc" // 按照 _count 升序排列
        },
        "size": 20
      }
    }
  }
}
 
- 限定聚合范围,默认情况下, Bucket 聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围,只要添加 query 条件即可。
 
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 50 // 只对 50 元以下的文档聚合
      }
    }
  },
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}
 
- 总结:
aggs 代表聚合,与 query 同级,此时 query 的作用是?- 限定聚合的的文档范围
 - 聚合必须的三要素: 
    
- 聚合名称
 - 聚合类型
 - 聚合字段
 
 - 聚合可配置属性有: 
    
- size :指定聚合结果数量
 - order :指定聚合结果排序方式
 - field :指定聚合字段
 
 
 
(3)DSL 实现 Metrics 聚合
我们要求获取每个品牌的用户评分的 min 、 max 、 avg 等值
 我们可以利用 stats 聚合:
GET /hotel/_search
{
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      },
      "aggs": {               // 是 brands 聚合的子聚合,也就是分组后对每组分别计算
        "score_stats": {      // 聚合名称
          "stats": {          // 聚合类型,这里 stats 可以计算 min 、 max 、 avg 等
            "field": "score"  // 聚合字段,这里是 score
          }
        }
      }
    }
  }
}
 
结果如下:
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 11,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "brandAgg": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "贝壳",
          "doc_count": 9,
          "score_stats": {
            "count": 9,
            "min": 43,
            "max": 43,
            "avg": 43,
            "sum": 387
          }
        },
        {
          "key": "如家",
          "doc_count": 1,
          "score_stats": {
            "count": 1,
            "min": 56,
            "max": 56,
            "avg": 56,
            "sum": 56
          }
        },
        {
          "key": "汉庭",
          "doc_count": 1,
          "score_stats": {
            "count": 1,
            "min": 12,
            "max": 12,
            "avg": 12,
            "sum": 12
          }
        }
      ]
    }
  }
}
 
(4)RestAPI 实现聚合
- 组装request参数

 - 解析response中json参数

 
2.自动补全
(1)自定义分词器
- 使用拼音分词
 - lasticsearch 中分词器( analyzer )的组成包含三部分: 
  
- character filters :在 tokenizer 之前对文本进行处理。例如删除字符、替换字符
 - tokenizer :将文本按照一定的规则切割成词条( term )。例如 keyword ,就是不分词;还有 ik_smart
 - tokenizer filter :将 tokenizer 输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等
 
 
(2)completion suggester 查询
elasticsearch 提供了 Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词
 条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:
- 参与补全查询的字段必须是 completion 类型。
 - 字段的内容一般是用来补全的多个词条形成的数组。
 
// 自动补全查询
GET /hotel/_search
{
  "suggest": {
    "title_suggest": {
      "text": "s", // 关键字
      "completion": {
        "field": "brand", // 补全查询的字段
        "skip_duplicates": true, // 跳过重复的
        "size": 10 // 获取前 10 条结果
      }
    }
  }
}
 
3.数据同步
(1)elasticsearch 与 mysql 之间的数据同步

 

4.集群
(1)ES 集群的分布式存储
当新增文档时,应该保存到不同分片,保证数据均衡,那么 coordinating node 如何确定数据该存储到哪个分片呢?
 elasticsearch 会通过 hash 算法来计算文档应该存储到哪个分片:
 说明:
| shard = hash(_routing) % number_of_shards | 
|---|
- _routing 默认是文档的 id
 - 算法与分片数量有关,因此索引库一旦创建,分片数量不能修改!
 

(1)ES 集群的分布式查询
elasticsearch 的查询分成两个阶段:
- scatter phase :分散阶段, coordinating node 会把请求分发到每一个分片。
 - gather phase :聚集阶段, coordinating node 汇总 data node 的搜索结果,并处理为最终结果集返回给用户。

 








![[react] useState的一些小细节](https://img-blog.csdnimg.cn/direct/418e7951b9b94d9fa62d5f54724c8eae.png)










