Elasticsearch中文分词加拼音
网上可能有很多教程,我写这个只是记录一下自己学习的过程,给自己看的 。
中文分司网上搜了一下,用的IK分词器(https://github.com/medcl/elasticsearch-analysis-ik),拼音搜索插件用的是拼音分词器(https://github.com/medcl/elasticsearch-analysis-pinyin)。
IK分词器有两种分词模式:ik_max_word和ik_smart模式。
1、ik_max_word
会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
2、ik_smart
会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
安装IK分词器
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.1/elasticsearch-analysis-ik-7.4.1.zip
我的es是7.4所以装了7.4版本
安装拼音分司器
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v7.4.1/elasticsearch-analysis-pinyin-7.4.1.zip
按装好分司器后,需在创建索引时指定所用的分词器。以下是PHP的示例代码
/**
* 获取创建索引时的分词配置信息
* @param $indexName 索引名称
* @return array
*/
protected function getIndexSettings($indexName)
{
return [
'index' => $indexName,
'body' => [
"settings" => [
"number_of_shards" => 1,
"number_of_replicas" => 1,
'analysis' => [
'analyzer' =>
[
'ik_pinyin_analyzer' =>
[
'type' => 'custom',
'tokenizer' => 'ik_smart',
'filter' => ['my_pinyin', 'word_delimiter',]
]
],
'filter' =>
[
'my_pinyin' =>
[
'type' => 'pinyin',
'keep_separate_first_letter' => false,
'keep_full_pinyin' => true,
'keep_original' => false,
'limit_first_letter_length' => 10,
'lowercase' => true,
'remove_duplicated_term' => true
]
]
],
],
],
];
}
public function createTestIndex()
{
$client=$this->getElasticClient();
//取索引的配置信息,创建的索引名称为test
$settings = $this->getIndexSettings('test');
//创建索引
$response = $client->indices()->create($settings);
return $response;
}
创建完索引后再创建映射。
{
"index":"test",
"body":{
"news":{
"_source":{
"enabled":true
},
"properties":{
"title":{
"type":"text"
},
"content":{
"type":"text"
},
"author":{
"type":"keyword"
}
}
}
}
}
上面是创建映射的json(请求体),news是类型名称,网上看了很多,都是这种结构,我反复试了很多次,都没有成功。不知道怎么回事。可能是7.4版本有些不一样吧。最后改成了下面的结构:
{
"index":"test",
"body":{
"_source":{
"enabled":true
},
"properties":{
"title":{
"type":"text"
},
"content":{
"type":"text"
},
"author":{
"type":"keyword"
}
}
}
}
type:text 表示对该字段做全文索引。(analyzed)
type:keyword 索引这个字段,使之可以被搜索,但是索引内容和指定值一样 (not_analyzed)
php代码如下:
public function createMap()
{
$client=$this->getElasticClient();
$params = [
'index' => 'test',
'body' => [
'_source' => [
'enabled' => true
],
'properties' => [
'title' => [
'type' => 'text'
],
'content' => [
'type' => 'text'
],
'author'=>[
'type'=>'keyword'
]
]
]
];
$response = $client->indices()->putMapping($params);
return $response;
}
接下来索引一个文档,看能否用中文和拼音搜索
public function index()
{
$client = $this->getElasticClient();
$indexName = $this->request->query('index', 'test');
$params = [
'type' => '_doc',
'index' => $indexName,
'body' =>
[
'title' => '英国通过“12月12日提前大选”的议案',
'content' => '当地时间29号晚上大约20:20左右、北京时间大约30日凌晨4:20,英国议会下院表决通过了首相鲍里斯·约翰逊提出的12月12日提前大选的简短议案。由于此前工党决定改变反对提前大选的立场,不出外界所料,约翰逊提出的“12月12日大选”的“一句话”议案在英国议会在英国议会下院以438票支持、20反对的表决结果,顺利获得通过。'
]
];
$response = $client->index($params);
return $response;
}
测试一下是否可以搜索得到:
POST:/test/_search
{
"query": {
"match": {
"title": "英国"
}
}
}
虽然能搜到,并不能说明就是按我设置的中文分司进行的分司。如果是默认的分把每个汉字拆开索引,也可以搜索得到。我又试了一拼音,发现什么也没有搜到。说明我的分词没有起做用。仔细想想,查查文档,发现在创建映射时,可以指定分词,于时删了索引,重建,在建映射时加入分司的设置:
{
"index":"test",
"body":{
"_source":{
"enabled":true
},
"properties":{
"title":{
"type":"text",
"analyzer":"ik_pinyin_analyzer"
},
"content":{
"type":"text",
"analyzer":"ik_pinyin_analyzer"
},
"author":{
"type":"keyword"
}
}
}
}
PHP代码如下:
public function createMap()
{
$client = $this->getElasticClient();
$params = [
'index' => 'test',
'body' => [
'_source' => [
'enabled' => true
],
'properties' => [
'title' => [
'type' => 'text',
"analyzer" => "ik_pinyin_analyzer"
],
'content' => [
'type' => 'text',
"analyzer" => "ik_pinyin_analyzer"
],
'author' => [
'type' => 'keyword'
]
]
]
];
$response = $client->indices()->putMapping($params);
return $response;
}
然后索引一段文章,再搜索试一下,发现一切正常,可以用拼音搜索了。
浙公网安备 33010602011771号