【笔记】Elasticsearch学习笔记
前言
Elasticsearch学习笔记
概念
- 文档(document):每条数据就是一个文档
- 词条(term):文档中按照语意分开后的词语
- 索引(index):相同类型文档的集合
- 映射(mapping):索引对文档字段的约束,类似于数据表的结构约束
Elasticsearch中的概念
MySQL与Elasticsearch的概念对比
| Elasticsearch中的概念 | 说明 | MySQL |
|---|---|---|
| Index | 索引,相同类型文档的集合。类似于MySQL的数据表 | Table |
| Document | 文档,每条数据就是一个文档,文档都是JSON格式字符串。类似于与MySQL的行 | Row |
| Field | 字段,JSON文档中的各个key。类似于MySQL的列 | Column |
| Mapping | 映射,JSON文档中各个value的约束。类似于MySQL的表结构 | Schema |
| DSL | JSON风格的请求语句,用来操作Elasticsearch实现CRUD的语句。类似于MySQL的SQL语句 | SQL |
ik分词器
- The IK Analysis plugin integrates Lucene IK analyzer (/302.html?target=http://code.google.com/p/ik-analyzer/) into elasticsearch, support customized dictionary.(Github)
添加扩展词
除了内置的词库,ik分词器还可以根据扩展词库进行分词
创建
/plugins/ik/config/ext.dic文件,文件内每行指定一条扩展词
添加停止词
如果定义了停止词库,ik分词器在遇到扩展词时将不会分词
创建
/plugins/ik/config/stopword.dic文件,文件内每行指定一条停止词
分词操作
"analyzer": "":指定分词的方式
standard:标准方式。逐字分词chinese:内置的中文分词。逐字分词ik_smart:ik分词器最少词ik_max_word:ik分词器最多词
"text": "":指定分词的内容
1 | POST http://127.0.0.1:9200/_analyze |
在指定索引库中进行分词操作
1 | POST http://127.0.0.1:9200/索引库名/_analyze |
对索引库的操作
新增索引库
- 在Elasticsearch中id通常定义为
keyword类型
type: "":字段数据类型字符串
text:可分词的文本keyword:精确值,不能被拆开的词数值
longintegershortbytedoublefloat布尔
boolean日期
date数组
elasticsearch中没有数组类型,但是任何数据类型都可以指定多个值
地理坐标
geo_point: "3.1415926, 3.1415926":地理上的一个点geo_shape: "LINESTARING(第一个点经度 第一个点纬度, 第二个点经度 第二个点纬度)":地理上由多个点组成的一个范围自动补全
completion:允许通过前缀关键字模糊搜索
index: "":是否创建倒排索引。如果字段参与搜索,才需要创建倒排索引;如果不需要搜索,就不用创建倒排索引
true:缺省值,创建倒排索引false:不创建倒排索引
analyzer: "":指定使用哪种分词器
standard:标准方式。逐字分词chinese:内置的中文分词。逐字分词ik_smart:ik分词器最少词ik_max_word:ik分词器最多词
properties: {"": "", "": ""}:字段的子字段copy_to: "其他字段名":将当前字段的值拷贝到其他字段(底层只是创建了一个索引,并不是真的拷贝了一份),这样当搜索其他字段时,当前字段的值也会被搜索到
1 | PUT http://127.0.0.1:9200/索引库名 |
指定自定义分词器
- 将pinyin分词器重新配置后,作为过滤器,与ik分词器组合成新的自定义分词器
- 创建索引库时,指定新增文档时使用的分词器为自定义分词器,指定查询文档时使用的分词器为ik分词器
character filter:在分词之间对原文档做处理
tokenizer:将文本按照指定的规则或分词器切成词条term,如果不分词就指定为keywordfilter:将tokenizer输出的词条交给指定过滤器或分词器作进一步处理
"analyzer": "":指定创建时使用的分词器"search_analyzer": "":指定搜索时使用的分词器
1 | PUT http://127.0.0.1:9200/索引库名 |
查询索引库
1 | GET http://127.0.0.1:9200/索引库名 |
删除索引库
1 | DELETE http://127.0.0.1:9200/索引库名 |
修改索引库
- 索引库不允许修改旧字段,只能添加新字段
1 | PUT http://127.0.0.1:9200/索引库名/_mapping |
对文档操作
新增文档
文档id:如果不指定文档id,则索引库会自动随机生成一个id
1 | POST http://127.0.0.1:9200/索引库名/_doc/文档id |
- 结果中
result如果为created表示新增成功 - 每次写操作都会导致
version自增
删除文档
1 | DELETE http://127.0.0.1:9200/索引库名/_doc/文档id |
- 结果中
result如果为deleted表示删除成功
删除所有文档
1 | POST http://127.0.0.1:9200/索引库名/_delete_by_query |
修改文档
全量修改
- 先通过文档id查询旧文档
- 如果查询到了旧文档,就删除旧文档,新增新文档
- 如果没有查询到旧文档,就直接新增文档
1 | PUT http://127.0.0.1:9200/索引库名/_doc/文档id |
- 结果中
result如果为updated表示全量修改成功 - 结果中
result如果为created表示新增成功
局部修改
- 只修改某个字段的值
1 | POST http://127.0.0.1:9200/索引库名/_update/文档id |
- 结果中
result如果为updated表示局部修改成功
查询文档
1 | GET http://127.0.0.1:9200/索引库名/_doc/文档id |
- 结果中
found如果为true表示查询成功,如果为false表示查询失败 - 如果查询成功,数据会存在
_source中
搜索文档的操作
1 | POST http://127.0.0.1:9200/索引库名/_search |
简单查询
查询所有
- 查询所有默认返回的结果并不是全部结果,只会返回部分结果
1 | POST http://127.0.0.1:9200/索引库名/_search |
查看分片信息
"explain": true:列出信息存储的节点位置
1 | POST http://127.0.0.1:9200/索引库名/_search |
全文检索
根据指定的单个字段全文检索
- 只要指定字段的关键字中,任意子关键字满足条件,即可查询出
1 | POST http://127.0.0.1:9200/索引库名/_search |
根据指定的多个字段全文检索
- 只要多个字段的关键字中,任意子关键字满足条件,即可查询出
- 多个字段全文检索比单个字段全文检索效率更低,推荐将字段的集合复制为一个单独字段
all进行单字段检索
"query": "":指定关键字"fields": ["", ""]:指定字段名
1 | POST http://127.0.0.1:9200/索引库名/_search |
精确查询
完全匹配
- 指定字段的值必须与关键字完全匹配时,才能查询出
1 | POST http://127.0.0.1:9200/索引库名/_search |
匹配数值范围
- 指定字段的值必须属于范围内时,才能查询出
gt:大于gte:大于等于lt:小于lte:小于等于
1 | POST http://127.0.0.1:9200/索引库名/_search |
地理查询
矩形范围
- 指定矩形左上角和右下角的坐标,查询矩形范围内的所有文档
top_left:矩形左上角的坐标
lat:经度lon:纬度
bottom_right:矩形右下角的坐标
lat:经度lon:纬度
1 | POST http://127.0.0.1:9200/索引库名/_search |
圆形范围
- 指定圆心和半径,查询圆形范围内的所有文档
"distance": "":指定半径距离"中心点坐标": "经度,纬度":指定中心点坐标
1 | POST http://127.0.0.1:9200/索引库名/_search |
复合查询
布尔查询
- 布尔查询是把多个简单查询语句进行组合,形成复合查询语句
must:(与)必须匹配所有子查询should:(或)选择性匹配子查询must_not:(非)必须不匹配所有子查询,不参与算分filter:必须匹配,不参与算分
1 | POST http://127.0.0.1:9200/索引库名/_search |
算分函数查询
Elasticsearch 5.0之前默认采用TF-IDF算法,会随着词频增加而无限增加Elasticsearch 5.0之后默认采用BM25算法,会随着词频增加而趋于水平
有加分规则
- 为了能人工干预算法默认的分数,可以采用
Function Score Query- 通过
query获取查询的文档 - 通过
filter过滤,得到需要加分的文档 - 通过运算函数,将运算函数的结果与原始的分进行组合运算
- 通过
boost_mode指定运算的方式
- 通过
function_score:通过算分函数重新算分
"query": {}:初始条件,通过简单查询添加条件,得到原始得分
"filter": {}:过滤条件,通过简单查询添加条件运算函数
weight:给定一个常量值作为函数结果field_value_factor:用文档的某个字段作为函数结果random_score:用一个随机数作为函数结果script_score:自定义一个公式,公式结果作为函数结果
boost_mode:指定算分方式
multiply:缺省值,将原始得分和额外分相乘add:将原始得分和额外分相加avg:将原始得分和额外分取平均值max:将原始得分和额外分取最大值min:将原始得分和额外分取最小值replace:将额外分数替换原始分数
1 | POST http://127.0.0.1:9200/索引库名/_search |
- 返回的数据中,
_score表示最终分数,分数越高排名越靠前
没有加分规则
- 没有加分规则实际上就是不进行加分
1 | POST http://127.0.0.1:9200/索引库名/_search |
搜索结果处理
排序
- 默认排序规则是按照相关度算分排序
order:指定排序规则
asc:升序desc:降序
1 | POST http://127.0.0.1:9200/索引库名/_search |
- 简化写法
1 | POST http://127.0.0.1:9200/索引库名/_search |
地理类型排序
- 不会参与打分
1 | POST http://127.0.0.1:9200/索引库名/_search |
简化写法
1 | POST http://127.0.0.1:9200/索引库名/_search |
分页
form+size的值不能大于10000
from:分页起始下标位置,默认为0size:每页的数据数,默认为10
1 | POST http://127.0.0.1:9200/索引库名/_search |
高亮
- 原理:后端得到数据后,先将关键字添加标签,再返回给前端;前端添加指定标签的样式,实现高亮
require_field_match:是否开启搜索字段与高亮字段匹配
true:缺省值,开启搜索字段与高亮字段匹配。如果匹配才会实现高亮,如果不匹配就无法实现高亮false:关闭搜索字段与高亮字段匹配。即便是不匹配也能实现高亮
pre_tags:添加标签前缀,如果没有指定,缺省值是<em>post_tags:添加标签后缀,如果没有指定,缺省值是</em>
1 | POST http://127.0.0.1:9200/索引库名/_search |
聚合查询
- 官方文档
- 聚合可以实现对文档数据的统计、分析、运算
- 聚合可以嵌套,在一个聚合的结果上继续做聚合
query:限定聚合条件,可以不指定聚合条件size:展示的原数文档的个数,0表示不展示原文档aggs:定义聚合,可以指定多个聚合
1 | POST http://127.0.0.1:9200/索引库名/_search |
- 返回的数据中,
aggregations.聚合名表示聚合的结果
桶聚合(Bucket)
Term Aggregation方式桶聚合:按照文档字段值分组,统计指定字段相同的文档的数量。类似于MySQL中的分组(Group By)
terms:Term方式的桶聚合field:指定参与聚合的字段名size:指定聚合结果数量,默认值为10_count:返回数据按照文档数量的排序规则
desc:缺省值,按照文档数量的降序排序asc:按照文档数量的降序升序
1 | POST http://127.0.0.1:9200/索引库名/_search |
aggregations.聚合名.buckets.key:文档的字段名aggregations.聚合名.buckets.doc_count:文档的个数
度量聚合(Metric)
- 在桶聚合的基础上,用于计算数据的值,包括文档个数、文档评分最小值、文档评分最大值、文档评分平均值、文档评分总和
- 如果没有在桶聚合的基础上,则将所有数据参与分值计算
1 | POST http://127.0.0.1:9200/索引库名/_search |
aggregations.聚合名.buckets.度量聚合名.count:文档的个数aggregations.聚合名.buckets.度量聚合名.min:文档评分最小值aggregations.聚合名.buckets.度量聚合名.max:文档评分最大值aggregations.聚合名.buckets.度量聚合名.avg:文档评分平均值aggregations.聚合名.buckets.度量聚合名.sum:文档评分总和
自动补全搜索
自动补全类型
completion:通过前缀关键字模糊搜索
field:指定需要补全查询的字段名skip_duplicates:跳过重复项size:查询结果的个数
1 | GET http://127.0.0.1:9200/索引库名/_search |
Elasticsearch集群
集群中节点的职责
- 默认情况下每个节点同时具有这4种职责
| 节点类型 | 配置参数 | 默认值 | 节点职责 |
|---|---|---|---|
| master eligible | node.master | true | 备选主节点:主节点可以管理和记录集群状态、决定分片在哪个节点、处理创建和删除索引库的请求 |
| data | node.data | true | 数据节点:存储数据、搜索、聚合、CRUD |
| ingest | node.ingest | true | 数据预处理节点:数据存储之前的预处理 |
| coordinating | 以上节点如果都为false,则coordinating为true | 无 | 协调节点:路由请求到其他节点,合并其他节点处理的结果,返回给用户 |
脑裂现象
- 主节点由于网络原因导致与其他节点失联,此时其他节点会重新选举出新的主节点,当旧的主节点恢复连接时,集群中会出现多个主节点,这种现象就是脑裂现象
- 当
选举票数 > (所有节点个数 + 1) / 2时,可以避免脑裂现象 - Elasticsearch7.x版本以上,选举算法直接作为了配置的缺省值,所以不需要任何配置即可解决脑裂现象
分布式新增
- 将得到的数据交给主节点,主节点通过计算
hash(文档id) % 所有节点个数的值,可以得到将数据存储到哪个分片 - 将数据交给指定节点进行存储
- 将数据交给其他节点进行备份
分布式查询
- 分散阶段(scatter phase):coordinating节点会把请求分发给集群中的每一个节点
- 聚集阶段(gather phase):coordinating节点会将从所有data节点中搜索到的结果进行汇总后返回给用户
故障转移
主节点会监控集群中所有节点的健康状态,当集群中其中一个节点宕机,会立即将宕机节点的数据重新备份给其他健康的节点,这就是故障转移
- 如果是数据节点宕机,直接进行转移数据
- 如果是主节点宕机,先进行主节点选举,再进行转移数据
如果宕机的节点恢复健康,则新的主节点会将备份数据重新从其他节点转移给恢复健康的节点