记住用户名密码
在使用mysql的时候,为了查询速度,我们都会使用索引这个东西(如果不知道什么叫索引,可以百度看看)
现在问题来了,索引对 like "%xx%" 是不生效的,这就意味着无法快速的模糊匹配查询数据,那么有什么办法解决这个问题吗?
例如有一组数据:
1
2
3
4
5
6
7
8
9
10
|
[ { "name": "恒富网", "keyword": "关键字123" }, { "name": "php程序员恒富网", "keyword": "个人介绍xxx" } ] |
如果需要查询 name 里面包含仙士可的,一般做法是直接遍历所有数据,一个个查,那么有什么快速的方法吗?
我们或许可以这样实现:
将name里面的所有文字拆分,每个文字都对应数组的索引
1
2
3
4
5
6
7
8
9
10
11
12
13
|
恒=>0 富=>0 网=>0
p=>1 h=>1 p=>1 程=>1 序=>1 员=>1 仙=>1 士=>1 可=>1 |
去重一下:
1
2
3
4
5
6
7
8
9
10
11
12
|
恒=>0 富=>0 网=>0
p=>1 h=>1 程=>1 序=>1 员=>1 恒=>1 富=>1 网=>1 |
合并一下:
1
2
3
4
5
6
7
8
9
|
恒=>[0,1] 富=>[0,1] 网=>[0,1]
p=>[1] h=>[1] 程=>[1] 序=>[1] 员=>[1] |
当我们需要查询仙士可时,首先查询 仙 对应的数组索引,然后查询 士,可,最后根据属性存储的数组索引做交集,交集出的数组索引则是查询出来的数据.
记录所有属性值对应的数据内容位置,根据属性值去找对应数据内容,通过属性值去确定一个数据的内容,这个索引方式就称为倒排索引
这个时候获取大家就发现了一个新的问题:当一个属性值存在几千个字符时,是不是代表着会存储几千个索引内容呢?这样岂不是非常耗费空间?
答案是:确实会,为了一定能够搜索到这个值,确实会存储几千个,但是实际上,文章内容并没有这么多个不同的字,中国常用字也就几千个,不管多少文章,其实常用汉字就几千个,并不会过于增加空间
这样的话,又可能会产生新的问题: 本身中文常用汉字只有几千个,那如果有几千万篇文章,岂不是意味着每一个字都会对应到几百万甚至上千万的文章id吗?这样岂不是跟没有索引一样?
这就涉及到了新的一个东西, 分词.
分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂得多、困难得多。
分词分为几种类型:
注 解 | ||
---|---|---|
具有名词功能的形容词。形容词代 |
||
取汉字“别”的声母。 | ||
取英语连词 conjunction的第1个 |
||
dg |
副词性语素。副词代码为 d,语素代码g前面置以D。 | |
取 adverb的第2个字母,因其 |
||
取英语叹词 exclamation的第1个 |
||
取汉字“方” | ||
绝大多数语素都能作为合成词的“ |
||
取英语 head的第1个字母。 | ||
取英语成语 idiom的第1个字母。 | ||
取汉字“简”的声母。 | ||
习用语尚未成为成语,有点“临时 |
||
取英语 numeral的第3个字母,n |
||
名词性语素。名词代码为 n,语素代码g前面置以N。 | ||
取英语名词 noun的第1个字母。 | ||
名词代码 n和“人(ren)”的声母并在 |
||
名词代码 n和处所词代码s并在一起。 | ||
“团”的声母为 t,名词代码n和t并在一起。 | ||
“专”的声母的第 1个字母为z,名词代码n和z并 |
||
取英语拟声词 onomatopoeia的第1 |
||
取英语介词 prepositional的第 |
||
取英语 quantity的第1个字母。 |
||
取英语代词 pronoun的第2个字母,因 |
||
取英语 space的第1个字母。 | ||
时间词性语素。时间词代码为 t,在语素的代码g前面置以T。 |
||
取英语 time的第1个字母。 | ||
取英语助词 auxiliary | ||
动词性语素。动词代码为 v。在语素的代码g前面置以V。 |
||
取英语动词 verb的第一个字母。 | ||
直接作状语的动词。动词和副词的 |
||
指具有名词功能的动词。动词和名 |
||
非语素字只是一个符号,字母 x通常用于代表未知数、符号。 | ||
取汉字“语”的声母。 | ||
取汉字“状”的声母的前一个字母 |
||
不可识别词及用户自定义词组。取 |
识别文章中的所有字符,通过预设定/或者ai自动识别的方案,自动将一句话/一篇文章内的字符串拆分为一个个的词语:
1
|
php是世界上最好的语言. |
拆分为:
1
|
php 是 世界上 最好的 语言 |
中文分词方案有很多,例如 scws,THULAC,结巴分词,等等 中文分词方案.
在上面,我们了解到了倒排索引,了解了中文分词,那么lucene就是现成的使用倒排索引实现的全文搜索引擎.
lucene还附带了中文分词等解决方案.
为了使得lucene更好的标识存储,field的类型大致分为以下几种:
1:完全拆分字符实现索引
2:分词实现索引
3:只存储文档数据,不建立索引
4:只建立索引,数据不存储在文档
- 文档标明id存储
- 文档解析field
- 文档分析field,分词
- 建立索引,索引进入索引库
- 用户通过查询接口
- 创建查询语言
- lucene 执行查询,通过索引库获得数据
- 渲染数据
- 响应到用户端
在原来的lucene 全文搜索引擎中,它仅仅是一个全文搜索架构,提供了完整的查询引擎架构,如果需要使用它,那就意味着要自己实现各种存储,查询的调用.
elasticsearch 进一步封装了lucene,封装 restful api操作存储对象.并且实现了分布式存储架构
中文文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/intro.html
1
2
3
4
5
6
7
|
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:
新增一条数据:
1
2
3
|
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 }% |
获取一条数据:
1
2
|
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 条留言 其中:访客:0 条, 博主:0 条