elasticsearch 入门原理解析
前言
在使用mysql的时候,为了查询速度,我们都会使用索引这个东西
现在问题来了,索引对 like "%xx%" 是不生效的,这就意味着无法快速的模糊匹配查询数据,那么有什么办法解决这个问题吗?
倒排索引
例如有一组数据:
[
{
"name": "仙士可",
"keyword": "关键字123"
},
{
"name": "php程序员仙士可",
"keyword": "个人介绍xxx"
}
]
复制
如果需要查询 name 里面包含仙士可的,一般做法是直接遍历所有数据,一个个查,那么有什么快速的方法吗?
我们或许可以这样实现:
将name里面的所有文字拆分,每个文字都对应数组的索引
仙=>0
士=>0
可=>0
p=>1
h=>1
p=>1
程=>1
序=>1
员=>1
仙=>1
士=>1
可=>1
复制
去重一下:
仙=>0
士=>0
可=>0
p=>1
h=>1
程=>1
序=>1
员=>1
仙=>1
士=>1
可=>1
复制
合并一下:
仙=>[0,1]
士=>[0,1]
可=>[0,1]
p=>[1]
h=>[1]
程=>[1]
序=>[1]
员=>[1]
复制
当我们需要查询仙士可时,首先查询 仙 对应的数组索引,然后查询 士,可,最后根据属性存储的数组索引做交集,交集出的数组索引则是查询出来的数据.
记录所有属性值对应的数据内容位置,根据属性值去找对应数据内容,通过属性值去确定一个数据的内容,这个索引方式就称为倒排索引
分词
这个时候获取大家就发现了一个新的问题:当一个属性值存在几千个字符时,是不是代表着会存储几千个索引内容呢?这样岂不是非常耗费空间?
答案是:确实会,为了一定能够搜索到这个值,确实会存储几千个,但是实际上,文章内容并没有这么多个不同的字,中国常用字也就几千个,不管多少文章,其实常用汉字就几千个,并不会过于增加空间
这样的话,又可能会产生新的问题: 本身中文常用汉字只有几千个,那如果有几千万篇文章,岂不是意味着每一个字都会对应到几百万甚至上千万的文章id吗?这样岂不是跟没有索引一样?
这就涉及到了新的一个东西, 分词.
分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂得多、困难得多。
分词分为几种类型:
词性编码 |
词性名称 |
注 解 |
---|---|---|
Ag |
形语素 |
形容词性语素。形容词代码为 a,语素代码g前面置以A。 |
a |
形容词 |
取英语形容词 adjective的第1个字母。 |
ad |
副形词 |
直接作状语的形容词。形容词代码 a和副词代码d并在一起。 |
an |
名形词 |
具有名词功能的形容词。形容词代码 a和名词代码n并在一起。 |
b |
区别词 |
取汉字“别”的声母。 |
c |
连词 |
取英语连词 conjunction的第1个字母。 |
dg |
副语素 |
副词性语素。副词代码为 d,语素代码g前面置以D。 |
d |
副词 |
取 adverb的第2个字母,因其第1个字母已用于形容词。 |
e |
叹词 |
取英语叹词 exclamation的第1个字母。 |
f |
方位词 |
取汉字“方” |
g |
语素 |
绝大多数语素都能作为合成词的“词根”,取汉字“根”的声母。 |
h |
前接成分 |
取英语 head的第1个字母。 |
i |
成语 |
取英语成语 idiom的第1个字母。 |
j |
简称略语 |
取汉字“简”的声母。 |
k |
后接成分 |
|
l |
习用语 |
习用语尚未成为成语,有点“临时性”,取“临”的声母。 |
m |
数词 |
取英语 numeral的第3个字母,n,u已有他用。 |
Ng |
名语素 |
名词性语素。名词代码为 n,语素代码g前面置以N。 |
n |
名词 |
取英语名词 noun的第1个字母。 |
nr |
人名 |
名词代码 n和“人(ren)”的声母并在一起。 |
ns |
地名 |
名词代码 n和处所词代码s并在一起。 |
nt |
机构团体 |
“团”的声母为 t,名词代码n和t并在一起。 |
nz |
其他专名 |
“专”的声母的第 1个字母为z,名词代码n和z并在一起。 |
o |
拟声词 |
取英语拟声词 onomatopoeia的第1个字母。 |
p |
介词 |
取英语介词 prepositional的第1个字母。 |
q |
量词 |
取英语 quantity的第1个字母。 |
r |
代词 |
取英语代词 pronoun的第2个字母,因p已用于介词。 |
s |
处所词 |
取英语 space的第1个字母。 |
tg |
时语素 |
时间词性语素。时间词代码为 t,在语素的代码g前面置以T。 |
t |
时间词 |
取英语 time的第1个字母。 |
u |
助词 |
取英语助词 auxiliary |
vg |
动语素 |
动词性语素。动词代码为 v。在语素的代码g前面置以V。 |
v |
动词 |
取英语动词 verb的第一个字母。 |
vd |
副动词 |
直接作状语的动词。动词和副词的代码并在一起。 |
vn |
名动词 |
指具有名词功能的动词。动词和名词的代码并在一起。 |
w |
标点符号 |
|
x |
非语素字 |
非语素字只是一个符号,字母 x通常用于代表未知数、符号。 |
y |
语气词 |
取汉字“语”的声母。 |
z |
状态词 |
取汉字“状”的声母的前一个字母。 |
un |
未知词 |
不可识别词及用户自定义词组。取英文Unkonwn首两个字母。(非北大标准,CSW分词中定义) |
识别文章中的所有字符,通过预设定/或者ai自动识别的方案,自动将一句话/一篇文章内的字符串拆分为一个个的词语:
php是世界上最好的语言.
复制
拆分为:
php 是 世界上 最好的 语言
复制
中文分词方案有很多,例如 scws,THULAC,结巴分词,等等 中文分词方案.
lucene
在上面,我们了解到了倒排索引,了解了中文分词,那么lucene就是现成的使用倒排索引实现的全文搜索引擎.
lucene还附带了中文分词等解决方案.
lucene 的大致存储结构为:
lucene field的类型:
为了使得lucene更好的标识存储,field的类型大致分为以下几种:
1:完全拆分字符实现索引
2:分词实现索引
3:只存储文档数据,不建立索引
4:只建立索引,数据不存储在文档
索引和查询流程为:
- 文档标明id存储
- 文档解析field
- 文档分析field,分词
- 建立索引,索引进入索引库
- 用户通过查询接口
- 创建查询语言
- lucene 执行查询,通过索引库获得数据
- 渲染数据
- 响应到用户端
elasticsearch
在原来的lucene 全文搜索引擎中,它仅仅是一个全文搜索架构,提供了完整的查询引擎架构,如果需要使用它,那就意味着要自己实现各种存储,查询的调用.
elasticsearch 进一步封装了lucene,封装 restful api操作存储对象.并且实现了分布式存储架构
中文文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/intro.html
安装与运行
docker 安装:
docker pull elasticsearch
sudo docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-v ~/docker/volumn/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v ~/docker/volumn/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch
复制
访问:http://127.0.0.1:9200/ 出现数据则表示运行成功
使用
elasticsearch 使用restful api 请求规范操作,意味着你可以使用postman,curl,等等http客户端进行操作.
例如使用curl:
新增一条数据:
tioncico@acbc32866c55 ~ % curl -X PUT --header 'Content-Type: application/json' http://127.0.0.1:9200/databasename/tablename/1 -d \
'{"name":"仙士可","age":"24"}'
{"_index":"databasename","_type":"tablename","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"created":true}%
复制
获取一条数据:
tioncico@acbc32866c55 ~ % curl -X GET --header 'Content-Type: application/json' http://127.0.0.1:9200/databasename/tablename/1
{"_index":"databasename","_type":"tablename","_id":"1","_version":1,"found":true,"_source": {"name":"仙士可","age":"24"}}% tioncico@acbc32866c55 ~ %
复制
其他高级搜索操作可查看官方文档
- 点赞
- 收藏
- 关注作者
评论(0)