• 【Elasticsearch教程19】IK分词器 ik_max_word、ik_smart


    一、IK分词器

    全民制作人,大家好,我是练习时长2年半的个人练习生亚瑟王,喜欢ES、钢琴、鼓励队友。

    ES默认的standard分词器对中文不友好,会将中文分割成一个个汉字。对于中文分词,目前比较常用的是IK分词器。IK分词器的作者对这个项目维护的比较积极,能紧跟ES的最新版本。

    安装IK分词器的教程网上太多了,我这里就不再赘述了。本篇博客仅仅记录我自己学习IK的一些小小心得。

    1. 创建测试的Mapping和数据

    • nameanalyzer是默认的standard,对于姓名这样的中文,适合用standard,因为姓名中一般没有固定的词组。
    • wordanalyzerik_max_wordsearch_analyzerik_smart
    PUT pigg_test_ik
    {
        "mappings":{
            "properties":{
                "name":{
                    "type":"text",
                    "analyzer":"standard"
                },
                "word":{
                    "type":"text",
                    "analyzer":"ik_max_word",
                    "search_analyzer":"ik_smart"
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    插入测试数据

    PUT pigg_test_ik/_doc/1
    {
      "name": "亚瑟王",
      "word": [
          "亚瑟王爱弹琴"
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. 查看文档如何存储

    执行如下命令,看字符串是如何拆分后索引的

    GET pigg_test_ik/_doc/1/_termvectors?fields=name
    GET pigg_test_ik/_doc/1/_termvectors?fields=word
    
    • 1
    • 2
    字段词条
    name亚、瑟、王
    word亚瑟、王、亚瑟王、爱、弹琴

    3. 在name上match查询

    • 因为name是"analyzer":"standard",所以搜索的关键词会拆成一个个独立的字。
    • 只要关键词中包含亚、瑟、王中任意一个字,都算匹配成功。
    GET pigg_test_ik/_search
    {
      "query": {
        "match": {
          "name": "i瑟" //拆成"i"和"瑟","瑟"命中文档
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 但是如果修改matchoperatorand,则需要所有字全部命中
    GET pigg_test_ik/_search
    {
      "query": {
        "match": {
          "name": {
            "query": "i瑟", //因为有"i",所以没有匹配到文档
            "operator": "and"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4. 在word上match查询

    word字段上为啥analyzerik_max_word,而search_analyzerik_smart呢?

    • ik_max_word会尽可能拆分出更多的词条组合
    • ik_smart则相对智能,不会拆的很细

    我们先来看下这2个分析器对亚瑟王爱弹琴是如何处理的。

    POST pigg_test_ik/_analyze
    {
      "analyzer": "ik_smart",
      "text": "亚瑟王爱弹琴"
    }
    
    POST pigg_test_ik/_analyze
    {
      "analyzer": "ik_max_word",
      "text": "亚瑟王爱弹琴"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    analyzer词条
    ik_smart (搜索时)亚瑟王、爱、弹琴
    ik_max_word (索引时)亚瑟、王、亚瑟王、爱、弹琴

    通过上表,可以看出在好处是保存文档时,已经索引尽可能多的词,而在搜索文档时,没有必要对搜索关键字拆分的很细,这样提高了查询的效率。

    "亚瑟王"会拆分成"亚瑟王"这1个词条,直接拿"亚瑟王"去匹配文档,可以匹配成功

    GET pigg_test_ik/_search
    {
      "query": {
        "match": {
          "word": "亚瑟王" //会拆分成"亚瑟王"这1个词条,直接拿"亚瑟王"去匹配文档,可以匹配成功
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    "瑟王"会拆分成"瑟""王"这2个词条,"瑟"这个字匹配不到文档,但是"王"这个字可以匹配到文档

    GET pigg_test_ik/_search
    {
      "query": {
        "match": {
          "word": "瑟王" //会拆分成"瑟"和"王"这2个词条,"瑟"这个字匹配不到文档,但是"王"这个字可以匹配到文档
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用如下命令解释为何"瑟王"能匹配到文档

    GET pigg_test_ik/_explain/1
    {
      "query": {
        "match": {
          "word": "瑟王"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    返回结果中显示如下:

     "description" : "weight(word:王 in 1) [PerFieldSimilarity], result of:",
    
    • 1

    说明是"王"这个字匹配到文档的。

    5. 自定义字典

    在ik的config目录下创建ext.dic文本文件,添加一些自定义的扩展词
    在这里插入图片描述
    修改如下的配置文件,指定扩展字典的文件名
    在这里插入图片描述
    上面操作执行好了后,一定要重启ES,否则是不生效的。

  • 相关阅读:
    make menuconfig配置方法
    【概率论与数理统计(研究生课程)】知识点总结9(回归分析)
    洛谷P1406 方格填数 题解
    初学kotlin 01
    服务链路追踪 —— SpringCloud Sleuth
    Elasticsearch脑裂
    Java多线程编程怎么学?10年开发大佬用300案例进行详解,附带学习路线
    从LLaMA-Factory项目认识微调
    MongoDB时序集合
    多精度 simulator 中的 RL:一篇 14 年 ICRA 的古早论文
  • 原文地址:https://blog.csdn.net/winterking3/article/details/126729780