ES高级用法
# ES高级用法
# 1.数据聚合
数据聚合类似于数据库的groupby,聚合的字段不能是可分词的Text,否则就无法进行计算和分类
其中aggs聚合和query同级。
- aggs桶聚合:对文档分组,size指定聚合结果的数量,order指定聚合结果的排序方式,field指定聚合字段,类型使用"terms"。最终返回搜索结果的_count会统计桶内的文档数量。
- 度量聚合:用来计算一些值,最大值、平均值。子聚合类型使用"stat"
- 管道聚合:以其它聚合的结果为基础再做聚合
业务场景:点击搜索时,前端除了发送一个查询请求,还会发送一个聚合请求来缩小下面查询列表的范围。聚合过滤的结果要基于查询所得到的结果,也就是查询和聚合的查询结果要使用相同的条件,这样子查询虹桥后,聚合城市得到的结果才只有上海。

# 2.自动补全
拼音分词器pinyin-analyzer:对Text进行拼音分词。适合在创建倒排索引时使用,如果在搜索时也采用拼音分词器,那么搜索"狮子"也会把"师资"搜素出来,搜索狮子->shizi->匹配倒排索引中的shizi词条。

自定义分词器:先通过ik分词器->把分好的字段通过pinyin分词器。创建索引库时在settings中配置,tokenizer将文本按照分词器规则切割成词条,filter对上一步获取的词条做进一步的处理。
自动补全查询:①需要有completion类型的字段,并且字段值是多词条的数组(用String数组或者集合存储)②suggest查询
DSL语句分析:
- 构建了两个分词器text_anlyzer和completion_analyzer,其中text_anlyzer对text进行了切割分词,而completion_analyzer针对的是keyword不进行切割分词。
- "filter"下面自定义了更详细的配置,包括是否保留中文作为terms词条、是否保留拼音全拼。
- "mapping"中每个字段的analyzer用来指定创建索引时使用哪种分词器,search_analyzer指明搜索时采用哪种分词器。
- 向索引库中插入数据时,后端需要向建立自动补全的字段的值(keyword)填入suggestion字段。
PUT /hotel
{
"settings": {
"analysis": {
"analyzer": {
"text_anlyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
},
"completion_analyzer": {
"tokenizer": "keyword",
"filter": "py"
}
},
"filter": {
"py": {
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_original": true,
"limit_first_letter_length": 16,
"remove_duplicated_term": true,
"none_chinese_pinyin_tokenize": false
}
}
}
},
"mappings": {
"properties": {
"name":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart",
"copy_to": "all"
},
"all":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart"
},
"suggestion":{
"type": "completion",
"analyzer": "completion_analyzer"
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 3.数据同步
数据库数据变化时要保证Elasticsearch的数据也要同步变化。当搜索业务和数据库不在同一个微服务时需要另外考虑。
方案一:同步调用,先改数据库->再改es
方案二:异步通知,写完数据库后通过MQ发布通知,此时数据库服务结束。es收到消息通知执行业务。
方案三:canal监听数据库binlog,然后通知es数据变更情况。
采用RabbitMQ方案:
- MQ基于内存,因此插入数据库业务消息不需要传递整个对象,传递给一个对象的id即可。后续消费者再根据id从数据库中读取数据进行插入。
- 插入和更新可以写在同一个api,这是基于es查询的特性。
# 4.ES集群
海量数据存储问题:将索引库数据逻辑上分成N个分片,存储到多个节点
单点故障问题:将分片数据在不同节点备份
集群脑裂问题:当主节点宕机后(其它节点因为网络问题和当前主节点连接不上),其他节点会选举一个成为主节点,此时若先前的主节点恢复,则做增删改时会同时有多个主节点进行控制,最终造成数据不一致。依次规定要想选主节点成功,选票必须超过(候选节点+1)/2。
es节点类型:
- 候选主节点:参与集群选主
- data节点:数据的crud
- coordinator协调节点:路由请求到其它节点,合并查询结果
新增文档流程:当新增一个文档(数据),会对文档的id进行哈希算法再加取余运算(分片大小),最终根据结果存储到对应的分片(注意得到的结果是分片i,而不是节点i)。如果查询时不指定id,比如MatchAll,那么会把请求发送到每一个分片上,最终由协调节点来汇总搜索结果。
故障转移:主节点会监控集群中的节点状态,如果有节点宕机,会立刻将宕机节点的分片数据迁移到其他节点上面确保数据安全。