ES的分词器主要由三部分组成:
(1)原始文本处理-charactor filters
对原始文本进行处理。
(2)切词-tokenizer
按照规则进行切词。
(3)单词处理-token filters
将切词获取的单词进行加工。如大小写转化,删除stopwords,增加同义词等。
下面是一个自定义分词器的案例,自定义分词器的以上三部分内容。
# custom_analyzer - 自定义分词器的名称
# char_filter - 原始文本预处理
# tokenizer - 按照指定的规则切词
# filter - 将切词后的结果进行加工
# _english_ 英文停用词,如 a,an,the
PUT /test_analyzer_index_001
{
"settings": {
"analysis": {
"analyzer": {
"custom_analyzer":{
"type":"custom",
"char_filter":["emoticons"],
"tokenizer": "threeVerticalLine",
"filter":["english_stop"]
}
},
"char_filter": {
"emoticons":{
"type" : "mapping",
"mappings" : [
":) => _happy_",
":( => _sad_"
]
}
},
"tokenizer": {
"threeVerticalLine":{
"type":"pattern",
"pattern":"(\\|\\|\\|)"
}
},
"filter": {
"english_stop":{
"type":"stop",
"stopwords":"_english_"
}
}
}
},
"mappings": {
"dynamic": "strict",
"properties": {
"remark": {
"type": "text",
"analyzer": "custom_analyzer",
"search_analyzer": "custom_analyzer"
}
}
}
}
analyzer 用于指定对插入ES中的数据使用的分词器
search_analyzer 用于指定查询入参使用的分词器
POST test_analyzer_index_001/_analyze
{
"analyzer": "custom_analyzer",
"text": "进口药品|注册证H20130650|||进口药品注册证h20130650|||h20130650_haha_a_the|||tom :)|||jack :(|||a|||an|||the"
}
或者
POST test_analyzer_index_001/_analyze
{
"field":"remark",
"text": "进口药品|注册证H20130650|||进口药品注册证h20130650|||h20130650_haha_a_the|||tom :)|||jack :(|||a|||an|||the"
}
分词结果如下所示。
{
"tokens" : [
{
"token" : "进口药品|注册证H20130650",
"start_offset" : 0,
"end_offset" : 17,
"type" : "word",
"position" : 0
},
{
"token" : "进口药品注册证h20130650",
"start_offset" : 20,
"end_offset" : 36,
"type" : "word",
"position" : 1
},
{
"token" : "h20130650_haha_a_the",
"start_offset" : 39,
"end_offset" : 59,
"type" : "word",
"position" : 2
},
{
"token" : "tom _happy_",
"start_offset" : 62,
"end_offset" : 68,
"type" : "word",
"position" : 3
},
{
"token" : "jack _sad_",
"start_offset" : 71,
"end_offset" : 78,
"type" : "word",
"position" : 4
}
]
}
由结果可知,分词时,先按照emoticons规则进行了原始文本处理,然后根据threeVerticalLine规则进行分词(即使用"|||"分词),最后根据english_stop规则对英文停用词进行去除。
下面来测试下查询效果。
PUT /test_analyzer_index_001/_doc/1
{
"remark": "进口药品|注册证H20130650|||进口药品注册证h20130650|||h20130650_haha_a_the|||tom :)|||jack :(|||a|||an|||the"
}
GET /test_analyzer_index_001/_search
{
"query": {
"match_all": {}
}
}
结果如下
{
"hits" : [
{
"_index" : "test_analyzer_index_001",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"remark" : "进口药品|注册证H20130650|||进口药品注册证h20130650|||h20130650_haha_a_the|||tom :)|||jack :(|||a|||an|||the"
}
}
]
}
}
term 查询对输入不做分词,会将输入作为一个整体,到倒排索引中查找准确的词项。
(1)场景1-可召回插入的数据
GET /test_analyzer_index_001/_search
{
"query": {
"term": {
"remark": "进口药品注册证h20130650"
}
}
}
(2)场景2-查询结果为空
以下查询结果为空,因为”进口药品|注册证H20130650|||进口药品注册证h20130650|||h20130650_haha_a_the|||tom :)|||jack :(|||a|||an|||the“在新增ES倒排索引时会进行分词,将”tom :)“转化为了”tom _happy_“,因此在倒排索引中存储的值为分词后的值:”tom _happy_“,因此使用”tom :)“查询不到数据。
GET /test_analyzer_index_001/_search
{
"query": {
"term": {
"remark": "tom :)"
}
}
}
match 查询对输入的查询条件进行分词,生成一个供查询的词项列表,然后每个词项逐个进行底层的查询,最终将结果进行合并。
(1)场景1-可召回插入的数据
分词后的入参为 ”进口药品|注册证H20130650“、”tom _happy_“ 和 ”jack _sad_“。
GET /test_analyzer_index_001/_search
{
"query": {
"match": {
"remark": "进口药品|注册证H20130650|||tom :)|||jack :("
}
}
}
(2)场景2-可召回插入的数据
分词后的入参为”tom _happy_“ 。
GET /test_analyzer_index_001/_search
{
"query": {
"match": {
"remark": "tom :)"
}
}
}