文章目录
- 三、深入 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 的搜索结果,并处理为最终结果集返回给用户。