• 【Elasticsearch教程20】Pinyin拼音分词器 以及多音字修改


    1. 前言

    在开发企业项目时,根据拼音搜索是很常见的场景,比如:

    • 人员通讯录,不确定人名具体是哪个汉字,只知道读音,可以输入汉字+全拼音、汉字+拼音首字母、拼音首字母等
    • 股票名称,炒股的人都知道,股票太多,记住所有股票code是不可能的,所以常用拼音首字母查股票。

    在这里插入图片描述
    在这里插入图片描述
    Medcl大佬为我们提供了Pinyin分词器,可以让我们非常方便的使用拼音搜索文档。

    2. pinyin分词器的多音字的错误修改

    网上关于pinyin分词器的安装和使用的博客特别多,这里我就不赘述了。但是我得说一个非常重要的问题,目前我写博客时最新的版本8.x还是有这样的问题。虽然GitHub上,已经有人提出了这个Issue,但是目前还没有修复,所以我们就自己动手手动改改吧。

    问题就是多音字“银行”的“行”,pinyin分词器会把“yin hang”错误的转成“yin xing”,当你测试“中国银行”时它是对的,但是“建设银行”时就又错了。不信的话你自己试试看。

    这个时候需要修改下图中的jar包解压出来
    在这里插入图片描述
    然后修改如下图中文件polyphone.txt,注意千万不要一下子把"yin xing"替换成"yin hang"

    因为“隐形”、“银杏”这些词的拼音就是"yin xing"。这个你需要手动一个一个看好了改,我不确定这个问题是nlp-lang的问题还是pinyin分词器作者改的问题,我看nlp-lang1.7的源代码这个文件里“银行”确实是对的"yin hang"。

    改好后,再重新打成nlp-lang-1.7.jar包,替换上图的那个nlp-lang-1.7.jar文件,然后重启ES就行啦。
    在这里插入图片描述

    3. 案例

    Pinyin分词器的配置参数还是比较多的,可以参考它GitHub的说明,
    这些配置一定要认真配,不同的配置,出来的搜索效果是不同的。

    3.1 创建Mapping

    • 我把拼音分词器作用在name.pinyin这个子字段上,因为name这个主字段按照"standard"分词有用;
    • 我这么设计适合人名搜索、股票名称搜索这些值比较短的场景;
    • 如果是文章内容,留言评论这些内容长的,一般按照IK分词就行,如果非要支持拼音搜索,可以把IK+Pinyin组合起来,设置tokenizer为ik_smart,filter为pinyin;
    PUT pigg_test_pinyin
    {
        "settings":{
            "analysis":{
                "analyzer":{
                    "pinyin_analyzer":{
                        "tokenizer":"my_pinyin"
                    }
                },
                "tokenizer":{
                    "my_pinyin":{
                        "type":"pinyin",
                        "keep_first_letter":true,
                        "keep_separate_first_letter":true,
                        "keep_full_pinyin":true,
                        "remove_duplicated_term":true
                    }
                }
            }
        },
        "mappings":{
            "properties":{
                "name":{
                    "type":"text",
                    "analyzer":"standard",
                    "fields":{
                        "pinyin":{
                            "type":"text",
                            "analyzer":"pinyin_analyzer"
                        }
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3.2 插入测试文档

    PUT pigg_test_pinyin/_doc/1
    {
      "name": "亚瑟王"
    }
    
    PUT pigg_test_pinyin/_doc/2
    {
      "name": "鼓励王"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.3 测试拼音搜索

    按照中文:

    GET pigg_test_pinyin/_search
    {
      "query": {
        "match": {
          "name.pinyin": {
            "query": "瑟王",
            "operator": "and"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    按照中文+拼音全拼:

    GET pigg_test_pinyin/_search
    {
      "query": {
        "match": {
          "name.pinyin": {
            "query": "亚sewang",
            "operator": "and"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    按照中文+拼音首字母:

    GET pigg_test_pinyin/_search
    {
      "query": {
        "match": {
          "name.pinyin": {
            "query": "亚sw",
            "operator": "and"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    按照拼音首字母:

    GET pigg_test_pinyin/_search
    {
      "query": {
        "match": {
          "name.pinyin": {
            "query": "ysw",
            "operator": "and"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.4 查看拼音分词后结果

    第1种方法:

    GET pigg_test_pinyin/_doc/1/_termvectors?fields=name.pinyin
    
    • 1

    第2种方法:

    GET pigg_test_pinyin/_analyze
    {
      "analyzer" : "pinyin_analyzer",
      "text" : "亚瑟王"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    通过上面2种方法,都可以发现分词结果如下:

    y, s, w, ysw, ya, se, wang
    
    • 1

    这是因为我设置了"keep_separate_first_letter":true,这样拼音的首字母ysw会再次拆分成y, s, w
    这样我们搜索"亚sw"时,就能匹配到文档了。

    4. 结语

    作为大龄程序员,30多岁了,不需要涉及太多技术,得潜心专研一两个技术,并戒掉浮躁,在项目实践中打磨自己。
    所以光看文档、博客是没有用的,只有动手实践去解决业务问题,才会有更好的成长。

  • 相关阅读:
    线性代数 第五章 特征值与特征向量
    Vue3 - 事件 API 新标准(如何在 Vue3 中怎么用事件总线实现兄弟组件通信?相比 Vue2 有什么不同?)
    《向量数据库指南》——向量数据库是小题大作的方案?
    如何让 Source Insight 识别 AUTOSAR 宏定义 FUNC
    【LeetCode每日一题】——213.打家劫舍 II
    【目标检测】边界框回归与variances参数的作用
    链表经典面试题之二
    智能巡检系统可以应用在哪些地方?巡检系统有什么优势?
    从React源码角度看useCallback,useMemo,useContext
    面试核心技巧--spring篇
  • 原文地址:https://blog.csdn.net/winterking3/article/details/126900562