• 【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,否则是不生效的。

  • 相关阅读:
    《FFmpeg Basics》中文版-06-填充视频
    给 K8s 中的 Operator 添加 Webhook 功能【保姆级】
    URL转发请求
    2023年【金属非金属矿山(地下矿山)安全管理人员】考试题库及金属非金属矿山(地下矿山)安全管理人员模拟考试题
    linux 文本处理工具 cut 和 awk
    Android 使用ContentObserver监听SettingsProvider值的变化
    基于海鸥算法优化的Elman神经网络数据预测-附代码
    如何删除重复文件?简单操作法方法盘点!
    【LeetCode-278】第一个错误的版本
    MySQL 存储引擎、事务、多版本并发控制(MVCC)、数据类型
  • 原文地址:https://blog.csdn.net/winterking3/article/details/126729780