【笔记】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 (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 /_analyze |
在指定索引库中进行分词操作
1 | POST /索引库名/_analyze |
对索引库的操作
新增索引库
- 在Elasticsearch中id通常定义为
keyword
类型
type: ""
:字段数据类型字符串
text
:可分词的文本keyword
:精确值,不能被拆开的词数值
long
integer
short
byte
double
float
布尔
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 | POST /索引库名 |
指定自定义分词器
- 将pinyin分词器重新配置后,作为过滤器,与ik分词器组合成新的自定义分词器
- 创建索引库时,指定新增文档时使用的分词器为自定义分词器,指定查询文档时使用的分词器为ik分词器
character filter:在分词之间对原文档做处理
tokenizer
:将文本按照指定的规则或分词器切成词条term,如果不分词就指定为keyword
filter
:将tokenizer输出的词条交给指定过滤器或分词器作进一步处理
"analyzer": ""
:指定创建时使用的分词器"search_analyzer": ""
:指定搜索时使用的分词器
1 | PUT /索引库名 |
查询索引库
1 | GET /索引库名 |
删除索引库
1 | DELETE /索引库名 |
修改索引库
- 索引库不允许修改旧字段,只能添加新字段
1 | PUT /索引库名/_mapping |
对文档操作
新增文档
文档id
:如果不指定文档id,则索引库会自动随机生成一个id
1 | POST /索引库名/_doc/文档id |
- 结果中
result
如果为created
表示新增成功 - 每次写操作都会导致
version
自增
删除文档
1 | DELETE /索引库名/_doc/文档id |
- 结果中
result
如果为deleted
表示删除成功
修改文档
全量修改
- 先通过文档id查询旧文档
- 如果查询到了旧文档,就删除旧文档,新增新文档
- 如果没有查询到旧文档,就直接新增文档
1 | PUT /索引库名/_doc/文档id |
- 结果中
result
如果为updated
表示全量修改成功 - 结果中
result
如果为created
表示新增成功
局部修改
- 只修改某个字段的值
1 | POST /索引库名/_update/文档id |
- 结果中
result
如果为updated
表示局部修改成功
查询文档
1 | GET /索引库名/_doc/文档id |
- 结果中
found
如果为true
表示查询成功,如果为false
表示查询失败 - 如果查询成功,数据会存在
_source
中
搜索文档的操作
1 | GET /索引库名/_search |
简单查询
查询所有
- 查询所有默认返回的结果并不是全部结果,只会返回部分结果
1 | GET /索引库名/_search |
查看分片信息
"explain": true
:列出信息存储的节点位置
1 | GET /索引库名/_search |
全文检索
根据指定的单个字段全文检索
- 只要指定字段的关键字中,任意子关键字满足条件,即可查询出
1 | GET /索引库名/_search |
根据指定的多个字段全文检索
- 只要多个字段的关键字中,任意子关键字满足条件,即可查询出
- 多个字段全文检索比单个字段全文检索效率更低,推荐将字段的集合复制为一个单独字段
all
进行单字段检索
"query": ""
:指定关键字"fields": ["", ""]
:指定字段名
1 | GET /索引库名/_search |
精确查询
完全匹配
- 指定字段的值必须与关键字完全匹配时,才能查询出
1 | GET /索引库名/_search |
匹配数值范围
- 指定字段的值必须属于范围内时,才能查询出
gt
:大于gte
:大于等于lt
:小于lte
:小于等于
1 | GET /索引库名/_search |
地理查询
矩形范围
- 指定矩形左上角和右下角的坐标,查询矩形范围内的所有文档
top_left
:矩形左上角的坐标
lat
:经度lon
:纬度
bottom_right
:矩形右下角的坐标
lat
:经度lon
:纬度
1 | GET /索引库名/_search |
圆形范围
- 指定圆心和半径,查询圆形范围内的所有文档
"distance": ""
:指定半径距离"中心点坐标": "经度,纬度"
:指定中心点坐标
1 | GET /索引库名/_search |
复合查询
布尔查询
- 布尔查询是把多个简单查询语句进行组合,形成复合查询语句
must
:(与)必须匹配所有子查询should
:(或)选择性匹配子查询must_not
:(非)必须不匹配所有子查询,不参与算分filter
:必须匹配,不参与算分
1 | GET /索引库名/_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 | GET /索引库名/_search |
- 返回的数据中,
_score
表示最终分数,分数越高排名越靠前
没有加分规则
- 没有加分规则实际上就是不进行加分
1 | GET /索引库名/_search |
搜索结果处理
排序
- 默认排序规则是按照相关度算分排序
order
:指定排序规则
asc
:升序desc
:降序
1 | GET /索引库名/_search |
- 简化写法
1 | GET /索引库名/_search |
地理类型排序
- 不会参与打分
1 | GET /索引库名/_search |
简化写法
1 | GET /索引库名/_search |
分页
form
+size
的值不能大于10000
from
:分页起始下标位置,默认为0size
:每页的数据数,默认为10
1 | GET /索引库名/_search |
高亮
- 原理:后端得到数据后,先将关键字添加标签,再返回给前端;前端添加指定标签的样式,实现高亮
require_field_match
:是否开启搜索字段与高亮字段匹配
true
:缺省值,开启搜索字段与高亮字段匹配。如果匹配才会实现高亮,如果不匹配就无法实现高亮false
:关闭搜索字段与高亮字段匹配。即便是不匹配也能实现高亮
pre_tags
:添加标签前缀,如果没有指定,缺省值是<em>
post_tags
:添加标签后缀,如果没有指定,缺省值是</em>
1 | GET /索引库名/_search |
聚合查询
- 官方文档
- 聚合可以实现对文档数据的统计、分析、运算
- 聚合可以嵌套,在一个聚合的结果上继续做聚合
query
:限定聚合条件,可以不指定聚合条件size
:展示的原数文档的个数,0表示不展示原文档aggs
:定义聚合,可以指定多个聚合
1 | GET /索引库名/_search |
- 返回的数据中,
aggregations.聚合名
表示聚合的结果
桶聚合(Bucket)
Term Aggregation
方式桶聚合:按照文档字段值分组,统计指定字段相同的文档的数量。类似于MySQL中的分组(Group By)
terms
:Term方式的桶聚合field
:指定参与聚合的字段名size
:指定聚合结果数量,默认值为10_count
:返回数据按照文档数量的排序规则
desc
:缺省值,按照文档数量的降序排序asc
:按照文档数量的降序升序
1 | GET /索引库名/_search |
aggregations.聚合名.buckets.key
:文档的字段名aggregations.聚合名.buckets.doc_count
:文档的个数
度量聚合(Metric)
- 在桶聚合的基础上,用于计算数据的值,包括文档个数、文档评分最小值、文档评分最大值、文档评分平均值、文档评分总和
- 如果没有在桶聚合的基础上,则将所有数据参与分值计算
1 | GET /索引库名/_search |
aggregations.聚合名.buckets.度量聚合名.count
:文档的个数aggregations.聚合名.buckets.度量聚合名.min
:文档评分最小值aggregations.聚合名.buckets.度量聚合名.max
:文档评分最大值aggregations.聚合名.buckets.度量聚合名.avg
:文档评分平均值aggregations.聚合名.buckets.度量聚合名.sum
:文档评分总和
自动补全搜索
自动补全类型
completion
:通过前缀关键字模糊搜索
field
:指定需要补全查询的字段名skip_duplicates
:跳过重复项size
:查询结果的个数
1 | GET /索引库名/_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节点中搜索到的结果进行汇总后返回给用户
故障转移
主节点会监控集群中所有节点的健康状态,当集群中其中一个节点宕机,会立即将宕机节点的数据重新备份给其他健康的节点,这就是故障转移
- 如果是数据节点宕机,直接进行转移数据
- 如果是主节点宕机,先进行主节点选举,再进行转移数据
如果宕机的节点恢复健康,则新的主节点会将备份数据重新从其他节点转移给恢复健康的节点