Elasticsearch搜索原理
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
1、正排索引和倒排索引
- 正排索引
记录文档Id到文档内容、单词的关联关系
尚硅谷:1,3
docid |
content |
1 |
尚硅谷是最好的培训机构 |
2 |
php是世界上最好的语言 |
3 |
机构尚硅谷是如何诞生的 |
- 倒排索引
记录单词到文档id的关联关系,包含:
单词词典(Term DicTionary):记录所有文档的单词,一般比较大
倒排索引(Posting List):记录单词倒排列表的关联信息
例如:尚硅谷
1、Term Dictionary
尚硅谷
2、Posting List
DocId |
TF |
Position |
Offset |
1 |
1 |
0 |
<0,2> |
3 |
1 |
0 |
<0,2> |
DocId:文档id,文档的原始信息
TF:单词频率,记录该词再文档中出现的次数,用于后续相关性算分
Position:位置,记录Field分词后,单词所在的位置,从0开始
Offset:偏移量,记录单词在文档中开始和结束位置,用于高亮显示等
- 内存结构
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
B+Tree
每个文档字段都有自己的倒排索引
2、分词
分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es里面称为Analysis
- 分词机制
Character Filter |
对原始文本进行处理 |
例:去除html标签、特殊字符等 |
Tokenizer |
将原始文本进行分词 |
例:培训机构–>培训,机构 |
Token Filters |
分词后的关键字进行加工 |
例:转小写、删除语气词、近义词和同义词等 |
- 分词API
- 直接指定测试(指定分词器)
Request:
POST _analyze
{
“analyzer”: “standard”,
“text”:”hello 1111″
}
Response:
{
“tokens”: [
{
“token”: “hello”, #分词
“start_offset”: 0, #开始偏移
“end_offset”: 5, #结束偏移
“type”: “<ALPHANUM>”, #单词类型
“position”: 0 #位置
},
{
“token”: “world”,
“start_offset”: 6,
“end_offset”: 11,
“type”: “<NUM>”,
“position”: 1
}
]
}
- 针对索引的字段进行分词测试(利用该字段的分词器)
Request:
POST atguigu/_analyze
{
“field”: “name”,
“text”:”hello world”
}
Response:
{
“tokens”: [
{
“token”: “hello”,
“start_offset”: 0,
“end_offset”: 5,
“type”: “<ALPHANUM>”,
“position”: 0
},
{
“token”: “world”,
“start_offset”: 6,
“end_offset”: 11,
“type”: “<ALPHANUM>”,
“position”: 1
}
]
}
- 自定义分词器
Request:
POST _analyze
{
“tokenizer”: “standard”,
“filter”: [“lowercase”],
“text”:”Hello WORLD”
}
Response:
{
“tokens”: [
{
“token”: “hello”,
“start_offset”: 0,
“end_offset”: 5,
“type”: “<ALPHANUM>”,
“position”: 0
},
{
“token”: “world”,
“start_offset”: 6,
“end_offset”: 11,
“type”: “<ALPHANUM>”,
“position”: 1
}
]
}
- Elasticsearch自带的分词器
分词器(Analyzer) |
特点 |
Standard(es默认) |
支持多语言,按词切分并做小写处理 |
Simple |
按照非字母切分,小写处理 |
Whitespace |
按照空格来切分 |
Stop |
去除语气助词,如the、an、的、这等 |
Keyword |
不分词 |
Pattern |
正则分词,默认\w+,即非字词符号做分割符 |
Language |
常见语言的分词器(30+) |
- 中文分词
分词器名称 |
介绍 |
特点 |
地址 |
IK |
实现中英文单词切分 |
自定义词库 |
https://github.com/medcl/elasticsearch-analysis-ik |
Jieba |
python流行分词系统,支持分词和词性标注 |
支持繁体、自定义、并行分词 |
http://github.com/sing1ee/elasticsearch-jieba-plugin |
Hanlp |
由一系列模型于算法组成的java工具包 |
普及自然语言处理在生产环境中的应用 |
https://github.com/hankcs/HanLP |
THULAC |
清华大学中文词法分析工具包 |
具有中文分词和词性标注功能 |
https://github.com/microbun/elasticsearch-thulac-plugin |
- Character Filters
在进行Tokenizer之前对原始文本进行处理,如增加、删除或替换字符等
HTML Strip |
去除html标签和转换html实体 |
Mapping |
字符串替换操作 |
Pattern Replace |
正则匹配替换 |
注意:进行处理后,会影响后续tokenizer解析的position和offset
Request:
POST _analyze
{
“tokenizer”: “keyword”,
“char_filter”: [“html_strip”],
“text”:”<div><h1>B<sup>+</sup>Trees</h1></div>”
}
Response:
{
“tokens”: [
{
“token”: “””
B+Trees
“””,
“start_offset”: 0,
“end_offset”: 38,
“type”: “word”,
“position”: 0
}
]
}
- Token Filter
对输出的单词(term)进行增加、删除、修改等操作
Lowercase |
将所有term转换为小写 |
stop |
删除stop words |
NGram |
和Edge NGram连词分割 |
Synonym |
添加近义词的term |
Request:
POST _analyze
{
“tokenizer”: “standard”,
“text”:”a Hello World”,
“filter”: [
“stop”,
“lowercase”,
{
“type”:”ngram”,
“min_gram”:3,
“max_gram”:4
}
]
}
Response:
{
“tokens”: [
{
“token”: “hel”,
“start_offset”: 2,
“end_offset”: 7,
“type”: “<ALPHANUM>”,
“position”: 1
},
{
“token”: “hell”,
“start_offset”: 2,
“end_offset”: 7,
“type”: “<ALPHANUM>”,
“position”: 1
},
{
“token”: “ell”,
“start_offset”: 2,
“end_offset”: 7,
“type”: “<ALPHANUM>”,
“position”: 1
},
{
“token”: “ello”,
“start_offset”: 2,
“end_offset”: 7,
“type”: “<ALPHANUM>”,
“position”: 1
},
{
“token”: “llo”,
“start_offset”: 2,
“end_offset”: 7,
“type”: “<ALPHANUM>”,
“position”: 1
},
{
“token”: “wor”,
“start_offset”: 8,
“end_offset”: 13,
“type”: “<ALPHANUM>”,
“position”: 2
},
{
“token”: “worl”,
“start_offset”: 8,
“end_offset”: 13,
“type”: “<ALPHANUM>”,
“position”: 2
},
{
“token”: “orl”,
“start_offset”: 8,
“end_offset”: 13,
“type”: “<ALPHANUM>”,
“position”: 2
},
{
“token”: “orld”,
“start_offset”: 8,
“end_offset”: 13,
“type”: “<ALPHANUM>”,
“position”: 2
},
{
“token”: “rld”,
“start_offset”: 8,
“end_offset”: 13,
“type”: “<ALPHANUM>”,
“position”: 2
}
]
}
- 自定义分词api
Request:
PUT my_analyzer
{
“settings”: {
“analysis”: {
“analyzer”: {
“my”:{
“tokenizer”:”punctuation”,
“type”:”custom”,
“char_filter”:[“emoticons”],
“filter”:[“lowercase”,”english_stop”]
}
},
“tokenizer”: {
“punctuation”:{
“type”:”pattern”,
“pattern”:”[.,!?]”
}
},
“char_filter”: {
“emoticons”:{
“type”:”mapping”,
“mappings”:[
“:)=>_happy_”,
“:(=>_sad_”
]
}
},
“filter”: {
“english_stop”:{
“type”:”stop”,
“stopwords”:”_english_”
}
}
}
}
}
测试:
POST my_analyzer/_analyze
{
“analyzer”: “my”,
“text”:”l’m a person,and you?”
}
{
“tokens”: [
{
“token”: “l’m a _happy_ person”,
“start_offset”: 0,
“end_offset”: 15,
“type”: “word”,
“position”: 0
},
{
“token”: “and you”,
“start_offset”: 16,
“end_offset”: 23,
“type”: “word”,
“position”: 1
}
]
}
- 分词使用场景
- 索引时分词:创建或更新文档时,会对相应得文档进行分词(指定字段分词)
PUT my_test
{
“mappings”:{
“doc”:{
“properties”:{
“title”:{
“type”:”text”,
“analyzer”:”ik_smart”
}
}
}
}
}
- 查询时分词:查询时会对查询语句进行分词
POST my_test/_search
{
“query”:{
“match”:{
“message”:{
“query”:”hello”,
“analyzer”:”standard”
}
}
}
}
PUT my_test
{
“mappings”:{
“doc”:{
“properties”:{
“title”:{
“type”:”text”,
“analyzer”:”whitespace”,
“search_analyzer”:”standard” #查询指定分词器
}
}
}
}
}
一般不需要特别指定查询时分词器,直接使用索引时分词器即可,否则会出现无法匹配得情况,如果不需要分词将字段type设置成keyword,可以节省空间
3、IK分词器
- IK分词器的安装
- 下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
下载与安装的ES相对应的版本
2)解压,将解压后的elasticsearch文件夹拷贝到elasticsearch-5.6.8\plugins下,并重命名文件夹为analysis-ik
3)重新启动ElasticSearch,即可加载IK分词器
- IK分词器测试
IK提供了两个分词算法ik_smart 和 ik_max_word,其中 ik_smart 为最少切分,ik_max_word为最细粒度划分
- 最小切分:
在浏览器地址栏输入地址
http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员
输出的结果为:
{
“tokens” : [
{
“token” : “我”,
“start_offset” : 0,
“end_offset” : 1,
“type” : “CN_CHAR”,
“position” : 0
},
{
“token” : “是”,
“start_offset” : 1,
“end_offset” : 2,
“type” : “CN_CHAR”,
“position” : 1
},
{
“token” : “程序员”,
“start_offset” : 2,
“end_offset” : 5,
“type” : “CN_WORD”,
“position” : 2
}
]
}
2)最细切分:在浏览器地址栏输入地址
http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员
输出的结果为:
{
“tokens” : [
{
“token” : “我”,
“start_offset” : 0,
“end_offset” : 1,
“type” : “CN_CHAR”,
“position” : 0
},
{
“token” : “是”,
“start_offset” : 1,
“end_offset” : 2,
“type” : “CN_CHAR”,
“position” : 1
},
{
“token” : “程序员”,
“start_offset” : 2,
“end_offset” : 5,
“type” : “CN_WORD”,
“position” : 2
},
{
“token” : “程序”,
“start_offset” : 2,
“end_offset” : 4,
“type” : “CN_WORD”,
“position” : 3
},
{
“token” : “员”,
“start_offset” : 4,
“end_offset” : 5,
“type” : “CN_CHAR”,
“position” : 4
}
]
}
想要了解跟多关于大数据培训课程内容欢迎关注尚硅谷大数据培训,尚硅谷除了这些技术文章外还有免费的高质量大数据培训课程视频供广大学员下载学习。