Elasticsearch自带一套语言分析器(Analyzer),为世界上大多数语言提供良好的支持。Elasticsearch主要支持的语言有:阿拉伯语语、 亚美尼亚语、 巴斯克语、 巴西语、 保加利亚语、 加泰罗尼亚语、 中文、 捷克语、 丹麦语、 荷兰语、 英语、 芬兰语、 法语、 加利西亚语、 德语、 希腊语、 印地语、 匈牙利语、 印尼语、 爱尔兰语、 意大利语、 日语、 韩语、 库尔德语、 挪威语、 波斯语、 葡萄牙语、 罗马尼亚语、 俄语、 西班牙语、 瑞典语、 土耳其语和泰语。
这些语言分析器通常执行下面四个任务:
(1)将文本标记为单个词,如:
The quick brown foxes → [The, quick, brown, foxes]
(2)将词变成小写,如:
The → the
(3) 移除常用停用词,如:
[The, quick, brown, foxes] → [quick, brown, foxes]
(4)从切分的词干中获得词根,如:
foxes → fox
另外,根据某种特定的语言,每个分析器还可以对原始文本进行特定的转换,以便对该语言进行更好的搜索。例如,
(1) 英语分析器可以去掉所有格的形式,如:
John's → john
(2)法语分析器可以移除像l'、qu' 、¨或^之类的变音和元音符号,如:
l'église→eglis
(3) 德语分析器可以对词(term)进行归一化处理,如将单词中的ä和ae替换为a,将单词中的β替换为ss,如:
äüßerst→ausserst
下面我们就通过实例看看如何使用语言分析器:
PUT/my_index
{
"mappings": {
"blog": {
"properties": {
"title": {
"type": "string",
"analyzer":"english"
}
}
}
}
}
上面的例子就使用了ElasticSearch内置的english分析器在title字段上创建了一个my_index索引,类型为blog。ElasticSearch内置的分析器不需要安装配置,如果要使用IK或MMSeg之类的中文分析器,我们需要安装这些分析器的插件。我们可以使用下面的例子对title上字段上的english语言解析器进行测试:
GET /my_index/_analyze?field=title&text=I'm not happyabout the foxes
运行结果为:
{
"tokens":[
{
"token": "i'm",
"start_offset": 0,
"end_offset": 3,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "happi",
"start_offset": 8,
"end_offset": 13,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "about",
"start_offset": 14,
"end_offset": 19,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "fox",
"start_offset": 24,
"end_offset": 29,
"type": "<ALPHANUM>",
"position": 5
}
]
}
我们可以看到“I'mnot happy about the foxes”这句话被english分析器拆分为4个词:i'm,happi, about, fox;句子中的not,about和the三个单词是英文中的停用词,没有在被解析出来;而且,happy被解析为其词根happi,foxes被解析为其单数形式fox。通过english分析器解析句子后,我们的搜索会返回更多的结果,不管您输入happiness还是not happy,您都能搜索出这条记录。但是,这样解析之后,缺点是我们损失了原文的一部分信息,我们不能根据索引判断happy还是nothappy。
为了保持原文的精确度,我们可以使用多字段(multifields)进行索引。首先我们使用下面的语句删除my_index,然后使用多字段(multifields)对title字段进行两次索引,一次用english分析器,另一次用standard标准分词器。具体语句如下:
DELETE /my_index
PUT /my_index
{
"mappings": {
"blog":{
"properties": {
"title": {
"type": "string",
"fields": {
"english": {
"type": "string",
"analyzer": "english"
}
}
}
}
}
}
}
其中,title为主字段,用的是standard标准分词器;而后面的title.english子字段用的是english分析器。创建多字段索引后,我们可以利用下面的语句加载一些测试文本并检索:
PUT /my_index/blog/1 { "title": "I'm happy for this fox" } PUT /my_index/blog/2 { "title": "I'm not happy about my fox problem" } GET /_search { "query": { "multi_match": { "type": "most_fields", "query": "not happy foxes", "fields": [ "title", "title.english" ] } } }
在上面的搜索语句中,我们使用了most_fields关键字对尽可能多的字段进行匹配搜索。搜索结果如下:
{
"took":109,
"timed_out": false,
"_shards":{
"total": 48,
"successful": 48,
"failed": 0
},
"hits": {
"total":2,
"max_score": 0.10031386,
"hits":[
{
"_index": "my_index",
"_type": "blog",
"_id": "2",
"_score": 0.10031386,
"_source": {
"title": "I'm not happy about my fox problem"
}
},
{
"_index": "my_index",
"_type": "blog",
"_id": "1",
"_score": 0.07141322,
"_source": {
"title": "I'm happy for this fox"
}
}
]
}
}
我们可以看到,虽然两篇文档都没有含有我们要搜索的foxes,但是由于title字段上的english分析器将foxes转换为fox,所以这两篇文档都能被搜索出来。另外,由于第二篇文档含有我们要检索的单词not,所以第二篇文档的得分score较高,被排在第一篇文档之前。