0. 前言
国内企业出海是大势所趋,那么基于不同的语种进行分词就显得尤为重要,因为这会让用户的搜索体验更棒!
国内出海企业,会更偏向于选择欧美、中东这 2 个地区。
因此本文章也重点介绍英语、阿拉伯语的分词。
在 ES 中内置的分词器中,有一个叫 Language analyzers
,我们可以根据该分词器,自定义出符合业务需求的特定语言分词器。
1. 英语分词器
英语分词器一般而言应该满足以下要求
- 不区分大小写
- 去掉英语停顿词
- 具有相同的词干可以被认为是同一个词,例如 friends = fried
- 可能还需要有同义词,例如 quick = fast
Ok,基于以上要求,我们来自定义一个英文分词器。
- 不区分大小写,ES 有现成的 token filters:
lowercase token filter
- 去掉英语停顿词,ES 有现成的 token filters:
stop token filter
。并且 stop token filter 对多个语种均有支持 - 词干提取器,ES 有现成的 token filters:
stemmer token filter
。并且 stemmer token filter 对多个语种均有支持 - 同义词,ES 有现成的 token filters:
synonym token filter
, 不过需要我们提前定义好哪些词属于同义词。
OK,接下来,让我们看下具体的 Mapping 如何编写
PUT test9_en
{
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_custom_analyzer"
}
}
},
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"english_stop",
"english_stemmer",
"english_synonym"
]
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"english_synonym": {
"type": "synonym",
"synonyms": [ "quick => fast" ]
}
}
}
}
}
接下来,我们验证下效果
GET test9_en/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "the Friends quick"
}
输出如下
{
"tokens" : [
{
"token" : "friend",
"start_offset" : 4,
"end_offset" : 11,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "fast",
"start_offset" : 12,
"end_offset" : 17,
"type" : "SYNONYM",
"position" : 2
}
]
}
符合我们的预期:
- the 是停顿词,被过滤掉
- Friends 的词干为 friend;同时因为
lowercase token filter
的存在,大小被转换为小写了 - quick 和 fast 是同义词
ES 内置了非常丰富的 token filter
更多可以参考 ES token filter 官网
2. 阿拉伯语分词器
阿拉伯语分词器做法和英语类似,
对于 stop token filter
、stemmer token filter
均支持阿拉伯语。
在英语中,字母有大小写,而在阿拉伯语中,则存在不同字母的变形,因此我们需要将文本先做归一化处理。
这需要用到 ES 的 Normalizers
。用于将文本进行归一化处理。
本质上 lowercase token filter
就是一种 Normalizers
,即将所有文本都统一修改为小写
更详细的介绍,参考 ES Normalizers 官网
那么其 Mapping 如下
PUT test9_alb
{
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "arabic"
}
}
},
"settings": {
"analysis": {
"filter": {
"arabic_stop": {
"type": "stop",
"stopwords": "_arabic_"
},
"arabic_stemmer": {
"type": "stemmer",
"language": "arabic"
}
},
"analyzer": {
"arabic": {
"tokenizer": "standard",
"filter": [
"arabic_normalization",
"arabic_stop",
"arabic_stemmer"
]
}
}
}
}
}
我对阿拉伯语也不熟悉,这里就不进行效果验证了。
3. 结语
该篇我们探讨了如何实现英语、阿拉伯语的分词器。理论上其他语种的分词器也是类似的做法。