原创

elasticsearch 入门原理解析

温馨提示:
本文最后更新于 2021年03月05日,已超过 1,147 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

前言

在使用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 ~ %

其他高级搜索操作可查看官方文档

正文到此结束
本文目录