• 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;
        }
    

      然后索引一段文章,再搜索试一下,发现一切正常,可以用拼音搜索了。

  • 相关阅读:
    Java面向对象设计——购物车·
    查找

    栈和队列
    指针
    数组
    第四次博客——函数
    第三次博客作业
    第二次博客作业
    Java购物车大作业01
  • 原文地址:https://www.cnblogs.com/gomvc/p/11769827.html
Copyright © 2020-2023  润新知