Elasticsearch 是一个实时的分布式搜索分析引擎,它被用作全文检索、结构化搜索、分析以及这三个功能的组合,内部使用 Lucene 做索引与搜索。
1.es的实际应用
2.es全文检索简单介绍
基础概念带过一下
Index 可类比为DBMS的库
Type 可类比一张表
Document 可类比一条数据
全文检索要求一个词语或一段话在整个文档中被搜索,传统的数据库每个字段存储单个值,这对全文检索并不够。文本字段中的每个单词需要被搜索,对数据库意味着需要单个字段有索引多值(这里指单词)的能力,平常我们对字符串类型的字段一般不会建索引,一方面文本多变,没什么规律,另一方面对文本搜索的要求可能也不太大。Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。
一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。倒排索引也叫段segements,是一个数据集。假设我们有两个文档,每个文档的 content 域包含如下内容:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
es将每个文档的 content 域拆分成单独的 词(我们称它为 词条 或 tokens ),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。如下所示:
Term Doc_1 Doc_2
-------------------------
Quick | | X
The | X |
brown | X | X
dog | X |
dogs | | X
fox | X |
foxes | | X
in | | X
jumped | X |
lazy | X | X
leap | | X
over | X | X
quick | X |
summer | | X
the | X |
3.文档如何被搜索
倒排索引这种数据结构能帮助实现这个功能。相比特定词项出现过的文档列表,它会包含更多其它信息。它会保存每一个词项出现过的文档总数,在对应的文档中一个具体词项出现的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度,等等。这些统计信息允许 Elasticsearch 决定哪些词比其它词更重要,哪些文档比其它文档更重要。一个 Lucene 索引包含一个提交点和三个段 说明:无特别说明表示图是自创的
摘抄图
一个 Elasticsearch Index 由一个或者多个 shard (分片) 组成。
摘抄图
摘抄图
Lucene index 相当于 ES 的一个 shard。
摘抄图
近乎实时索引机制了解
一个新的document过来
1不断将 Document 写入到 In-memory buffer (内存缓冲区)。
2当满足一定条件?后内存缓冲区中的 Documents 刷新到 高速缓存(cache)。
3生成新的 segment ,这个 segment 还在 cache 中。
4这时候还没有 commit 到磁盘 ,但是已经可以被读取了。
摘抄图
数据从 buffer 到 cache 的过程是定期每秒刷新一次。所以新写入的 Document 最慢 1 秒就可以在 cache 中被搜索到,Document 从 buffer 到 cache 的过程叫做 refresh 。一般是 1 秒刷新一次,不需要进行额外修改。
分析器 将字符串转换为一串 tokens(标记)标记或者 terms(词条)
分词器 采用分割算法对字符串分词
个人理解是分析器是处理文档
分词器是处理输入的词条
分析器中可以定义分词器,分词器是为了分析器服务
分析器和分词器都生成词条或词根
过滤器 filter
过滤器应用范围更为广泛,可以过滤查询,过滤结果,聚合过滤,词元过滤等
词条terms 可以简单理解为一个单词或句子 比如family
词根term 可以简单理解为一个不可以再拆的单词 比如dog,dogs可以是词根也可以不是词根.如果dogs和dog同时出现,dogs不算词根,如果是 i have some dogs,dogs可以算词根
词元token 在这里词元和词条是一个意思
4.应用中搜素大致实现流程
数据如何到es
索引情况
{"st_bigscreen_search":{"aliases":{},"mappings":{"_doc":{"properties":{"__dummy__":{"type":"integer"},"attendee_parent_meeting":{"type":"long"},"category":{"type":"long"},"category_name":{"type":"text","fields":{"raw":{"type":"keyword"}},"analyzer":"ik_max_word"},"column_id":{"type":"text","fields":{"raw":{"type":"keyword"}},"analyzer":"ik_max_word"},"column_name":{"type":"text","fields":{"raw":{"type":"keyword"}},"analyzer":"ik_max_word"},...,"settings":{"index":{"number_of_shards":"5","provided_name":"st_bigscreen_search","creation_date":"1639432375199","analysis":{"analyzer":{"first_letter_analyzer":{"tokenizer":"first_letter_tokenizer"},"comma":{"type":"custom","tokenizer":"comma"},"ngram":{"type":"custom","tokenizer":"ngram"}},"tokenizer":{"first_letter_tokenizer":...
数据示例
不同类型的数据根据type区分,定义通用的helper,各业务实现helper,构建查询对象
添加MultiSearchRequestBuilder->
ElasticsearchClient.execute->
saveResponse
使用_msearch 查询
must指定了所有查询必须为 true 时将匹配到文档
should 表示或
走后台
直接调用yapi
5.es分析器插件简单介绍
使用了ik_max_word和ik_smart插件
ik_max_word会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
ik_smart会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
测试一下:
ik_max_word
ik_smart
使用场景思考
如果要求查询结果匹配度更高,应该考虑ik_max_word,要么可以考虑选择ik_smart。
一种较佳实践是:索引时用ik_max_word,在搜索时用ik_smart。
即:索引时最大化的将文章内容分词。创建索引时,设置mapping时指定分析器
6.简单看下es数据目录结构
Elasticsearch使用Lucene来处理分片级别的索引和查询,因此数据目录中的文件由Elasticsearch和Lucene写入。两者的职责都非常明确:
Lucene负责写和维护Lucene索引文件,
而Elasticsearch在Lucene之上写与功能相关的元数据,例如字段映射,索引设置和其他集群元数据。最终用户和支持功能。
data为数据目录结构
nodes是节点数据,启动了几个节点会有几个文件夹,从0开始
进入0
indices是索引文件
node.lock文件用于确保一次只能从一个数据目录读取/写入一个Elasticsearch相关安装信息。
_states是状态文件
看一下indices,是各个索引文件
通过uuid命名,可以用cat查看所有索引
看一下customer3
5个sharding,从0到4
index是Lucene索引文件
translog是事务日志
看一下index文件
segments是Lucene段
data格式的文件
查看文件内容,是二进制数据
看一下_states
global-前缀表示这是一个全局状态文件,而.st扩展名表示这是一个包含元数据的状态文件。
mysql和es全文搜索比较
全文搜索 姓名、电话、标题或组织名称。Mysql和es查询比较
Mysql查询比较慢
记录数2379
es查询 秒查 记录数一致
说明es全文建索性能相比mysql更佳
参考地址
Elasticsearch: 权威指南 | Elastic
目录 - elasticsearch中文文档