es
elasticsearch
类比数据库
Elasticsearch Index ~ Database
Types ~ Tables
Mapping ~ Schema
存储模型
Elasticsearch使用Apache Lucene,它是由Java编写的全文搜索库,由Doug Cutting(Apache Hadoop的创建者)内部开发,它使用称为倒排索引的数据结构,用于提供低延迟搜索结果。
文档(document)是Elasticsearch中的数据单位,并通过对文档中的术语进行标记来创建倒排索引,创建所有唯一术语的排序列表,并将文档列表与可以找到该词的位置相关联。
它非常类似于一本书背面的索引,其中包含书中的所有独特的单词和可以找到该单词的页面列表。当我们说一个文档被索引时,我们引用倒排索引。
为了提高可搜索性(例如,为小写字母和小写字提供相同的结果),首先分析文档并对其进行索引。
分析由两部分组成:
将句子标记成单词
将单词规范化为标准表单
默认情况下,Elasticsearch使用标准分析器
标准标记器(Standard tokenizer),用于在单词边界上分割单词
小写令牌过滤器(Lowercase token filter)将单词转换为小写
还有许多其他分析仪可用,您可以在文档中阅读它们。
注意:标准分析仪也使用停止令牌过滤器,但默认情况下禁用。
实现原理
write(写)/create(创建)操作实现原理
当您向协调节点发送请求以索引新文档时,将执行以下操作:
所有在Elasticsearch集群中的节点都包含:有关哪个分片存在于哪个节点上的元数据。协调节点(coordinating node)使用文档ID(默认)将文档路由到对应的分片。Elasticsearch将文档ID以murmur3作为散列函数进行散列,并通过索引中的主分片数量进行取模运算,以确定文档应被索引到哪个分片。
shard = hash(document_id) % (num_of_primary_shards)
当节点接收到来自协调节点的请求时,请求被写入到translog(我们将在后续的post中间讲解translog),并将该文档添加到内存缓冲区。如果请求在主分片上成功,则请求将并行发送到副本分片。只有在所有主分片和副本分片上的translog被fsync’ed后,客户端才会收到该请求成功的确认。
内存缓冲区以固定的间隔刷新(默认为1秒),并将内容写入文件系统缓存中的新段。此分段的内容更尚未被fsync’ed(未被写入文件系统),分段是打开的,内容可用于搜索。
translog被清空,并且文件系统缓存每隔30分钟进行一次fsync,或者当translog变得太大时进行一次fsync。这个过程在Elasticsearch中称为flush。在刷新过程中,内存缓冲区被清除,内容被写入新的文件分段(segment)。当文件分段被fsync’ed并刷新到磁盘,会创建一个新的提交点(其实就是会更新文件偏移量,文件系统会自动做这个操作)。旧的translog被删除,一个新的开始。
Update和Delete实现原理
删除和更新操作也是写操作。但是,Elasticsearch中的文档是不可变的(immutable),因此不能删除或修改。那么,如何删除/更新文档呢?
磁盘上的每个分段(segment)都有一个.del文件与它相关联。当发送删除请求时,该文档未被真正删除,而是在.del文件中标记为已删除。此文档可能仍然能被搜索到,但会从结果中过滤掉。当分段合并时(我们将在后续的帖子中包括段合并),在.del文件中标记为已删除的文档不会被包括在新的合并段中。
现在,我们来看看更新是如何工作的。创建新文档时,Elasticsearch将为该文档分配一个版本号。对文档的每次更改都会产生一个新的版本号。当执行更新时,旧版本在.del文件中被标记为已删除,并且新版本在新的分段中编入索引。旧版本可能仍然与搜索查询匹配,但是从结果中将其过滤掉。
indexed/updated文档后,我们希望执行搜索请求。我们来看看如何在Elasticsearch中执行搜索请求。
搜索相关性(Search Relevance)
相关性由Elasticsearch给予搜索结果中返回的每个文档的分数确定。用于评分的默认算法为tf / idf(术语频率/逆文档频率)。该术语频率测量术语出现在文档中的次数(更高频率=更高的相关性),逆文档频率测量术语在整个索引中出现的频率占索引中文档总数的百分比(更高的频率
==较少的相关性)。最终得分是tf-idf分数与其他因素(如词语邻近度(短语查询)),术语相似度(用于模糊查询)等的组合。
文档映射
静态映射
1).静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
2).设置文档静态映射
1 | PUT /es_db |
3).根据静态映射创建文档
1 | PUT /es_db/_doc/1 |
动态映射
1).Elasticsearch中不需要显示定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
2).动态映射默认有一个规则,即请求中文档的什么json类型对应es中什么数值类型,也可以通过动态模板(dynamic template)来覆盖这个规则,实现自定义推测规则,具体可以参考ES官网。
上述字段age被推测成long类型,如果非要往age中写入string类型的值,则会报错。如下图所示
数据类型
String 类型
string类型分为keyword和text,text会分词,keyword不会。
text是全文搜索类型,在建立索引和搜索时,输入的文本会经过分析器处理(Analyzed),分析器会对其进行过滤,分词,转换等操作。es内置了多种分析器,而且我们可以定义分析器。
只有text类型才能用于match,match_phrase等搜索语句,
ik_max_word 和 ik_smart
elasticsearch搜索中文分词优化
1、ik_max_word
会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
2、ik_smart
会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
两种 分词器的最佳实践: 索引时用 ik_max_word(面面俱到), 搜索时用 ik_smart(精准匹配)。
分词器 analyzer 和 search_analyzer
1,分词器 analyzer 的作用有二:
一是 插入文档时,将 text 类型字段做分词,然后插入 倒排索引。
二是 在查询时,先对 text 类型输入做分词, 再去倒排索引搜索。
2,如果想要“索引”和“查询”, 使用不同的分词器,那么 只需要在字段上 使用 search_analyzer。这样,索引只看 analyzer,查询就看 search_analyzer。
此外,如果没有定义,就看有没有 analyzer,再没有就去使用 ES 预设。
- Title: es
- Author: Ikko
- Created at : 2023-03-02 22:56:20
- Updated at : 2023-03-02 22:56:33
- Link: https://redefine.ohevan.com/2023/03/02/es/
- License: This work is licensed under CC BY-NC-SA 4.0.