问题描述
在我测试es数据库正则表达式的语法时,发现中文字符串始终识别不到,找到可以识别的表达式是.*
这让我百思不得其解
原因分析
究其原因:其实离不开elasticsearch数据库的原理——倒排列表,什么意思呢?假设我们存储一句话,那么,es数据库中的分词器会对这句话进行分词,然后将这些Token存入倒排列表。
-
举个例子来说,对于*“我真的好美丽”*这句话来说,分词器会将它识别为什么呢?
-
其实与分词器的选择有关,对于ES默认的分词器,会识别成下面这种格式
{ "tokens": [ { "token": "我", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "真", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "的", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 }, { "token": "好", "start_offset": 3, "end_offset": 4, "type": "<IDEOGRAPHIC>", "position": 3 }, { "token": "美", "start_offset": 4, "end_offset": 5, "type": "<IDEOGRAPHIC>", "position": 4 }, { "token": "丽", "start_offset": 5, "end_offset": 6, "type": "<IDEOGRAPHIC>", "position": 5 } ] }
你会发现,居然全是一个一个的单字!
-
-
而有了分词,es便将这些token做成了倒排列表,当你用正则表达式的文法严格搜索“我真的好美丽"时,会发现得到的结果是空集, 为什么这样答案可能你已经猜到了:因为正则表达式的文法过于严格,它严格地去匹配符合其文法规则的字符串,但是,es数据库的倒排索引中只有一个个的中文单字,找了一圈,它说,我没有找到这样的一句话,于是返回了空集。
问题解决
需要重建一个索引(数据库),并且在建立时指定使用的分词器
PUT website
{
"mappings": {
"properties": {
"user_id": { "type": "text" ,
"analyzer": "ik_max_word" , //对应 IK 的 ik_max_word 和 ik_smart 两种分词策略 也可以不写,不写则默认
"search_analyzer": "standard" //查询时使用的分词器
},
"name": {
"type": "text",
"analyzer": "english"
},
"age": { "type": "integer" },
"sex": { "type": "keyword" },
"birthday": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"address": {
"type": "text",
"index": false // 不分词
}
}
}
}
这样,我们更换了一种分词器ik_max_word
,我们来看一下它对这句话的分词结果
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "真的",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
},
{
"token": "好美",
"start_offset": 3,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
},
{
"token": "美丽",
"start_offset": 4,
"end_offset": 6,
"type": "CN_WORD",
"position": 3
}
]
}
有朋友可能会问:你这样也解决不了我们的需求呀? 这不是还没有我们要求的完整字段吗?
确实如此,所以就要求我们去寻找适合的分词方法,甚至自己来构造
对于本例而言,我们可以使用sample
分词器,它是ES原生的分词器,不会将任何的中文字符拆开,因此可以满足我们的需求。
推荐阅读:
- 了解分词器是什么,有哪些分词器
- 映射mapping是什么