• es ElasticSearch 中文分词


    原文链接:https://blog.csdn.net/qq_26803795/article/details/106522611

    文章目录

      • 一、前言
      • 二、内置分词器解析
        • 2.1、内置分词器梳理
        • 2.2、内置分词器对中文的局限性
      • 三、安装IK分词器
        • 3.1、下载IK分词器
        • 3.2、编译源码包
        • 3.3、上传编译好的包到Elasticsearch
      • 四、玩转ik分词器
        • 4.1、测试ik分词器
        • 4.2、来个小案例加深理解
      • 五、总结

    一、前言

    本文版本说明:

    1. ElasticSearch版本:7.7 (目前最新版)
    2. Kibana版本:7.7(目前最新版)

    前文咱们围绕Elasticsearch最新版进行了上万字的详细解析,相信看过的朋友对Elasticsearch及kibana等工具的极速安装配置印象深刻,也至少会对Elasticsearch有一个入门的掌握。
    前文链接:ElasticSearch最新版快速入门详解

    本文咱们深入一些,详细分析一下Elasticsearch的中文分词,并顺便解答和演示一下上篇文章有朋友对docker安装的Elasticsearch如何支持中文分词的疑问。好了,废话不多说,让我们开始吧!

    二、内置分词器解析

    咱们知道Elasticsearch之所以模糊查询这么快,是因为采用了倒排索引,而倒排索引的核心就是分词,把text格式的字段按照分词器进行分词并编排索引。为了发挥自己的优势,Elasticsearch已经提供了多种功能强大的内置分词器,它们的作用都是怎样的呢?能处理中文吗?咱们往下看!

    2.1、内置分词器梳理

    首先咱们可以对Elasticsearch提供的内置分词器的作用进行如下总结:

    分词器作用
    Standard ES默认分词器,按单词分类并进行小写处理
    Simple 按照非字母切分,然后去除非字母并进行小写处理
    Stop 按照停用词过滤并进行小写处理,停用词包括the、a、is
    Whitespace 按照空格切分
    Language 据说提供了30多种常见语言的分词器
    Patter 按照正则表达式进行分词,默认是W+ ,代表非字母
    Keyword 不进行分词,作为一个整体输出

    可以发现,这些内置分词器擅长处理单词和字母,所以如果咱们要处理的是英文数据的话,它们的功能可以说已经很全面了!那处理中文效果怎么样呢?下面咱们举例验证一下。

    2.2、内置分词器对中文的局限性

    1. 首先咱们创建一个索引,并批量插入一些包含中文和英文的数据:

      // 创建索引
      PUT /ropledata
      {
        "settings": { 
          "number_of_shards": "2", 
          "number_of_replicas": "0"
        } 
      }
      // 批量插入数据
      POST _bulk
      { "create" : { "_index" : "ropledata", "_id" : "1001" } }
      {"id":1,"name": "且听风吟","hobby": "music and movie"}
      { "create" : { "_index" : "ropledata", "_id" : "1002" } }
      {"id":2,"name": "静待花开","hobby": "music"}
      { "create" : { "_index" : "ropledata", "_id" : "1003" } }
      {"id":3,"name": "大数据","hobby": "movie"}
      { "create" : { "_index" : "ropledata", "_id" : "1004" } }
      {"id":4,"name": "且听_风吟","hobby": "run"}
      

      我的运行结果:
      在kibana的Dev Tools里执行情况:
      在这里插入图片描述
      查看Elasticsearch head里ropledata索引下的数据:
      在这里插入图片描述

    2. 使用iterm查询匹配的数据,分别对比中文英文:

      首先咱们查询爱好包含 ”music“ 的用户数据,根据咱们之前录入的数据,应该返回第一条和第二条才对,代码如下:

      POST /ropledata/_search
      {
        "query" : {
          "term" : {
            "hobby" : "music"
          }
        }
      }
      

      运行结果:
      在这里插入图片描述
      可以看到,很顺利的就查出来咱们期望的数据,所以在英文词汇下,即使是默认的分词器Standard也够用了。

      然后咱们试一下查找名字包含 “风吟” 的用户,理想情况下,应该能返回第一条和第四条数据才对,咱们执行如下代码:

      POST /ropledata/_search
      {
        "query" : {
          "term" : {
            "name" : "风吟"
          }
        }
      }
      

      运行结果:
      在这里插入图片描述
      我们可以发现,查中文词汇居然什么都没有匹配到,好奇怪呀!

      疑问一:为什么在默认分词器下,不能查找到词汇呢?

      因为咱们中文是非常博大精深的,词汇是由多个汉字组成的,不像英文,一个词汇就是一个单词,比如“music”对应音乐,汉字需要两个字才可以表示。而内置分词器是没有考虑到这类情况的,所以它们切分汉字时就会全部切分成单个汉字了,因此咱们找不到“风吟”这条数据,但是应该可以找到“风”这条数据,咱们接下来试一下。

      根据刚才的解释,咱们查找一个包含 “风” 的数据,代码如下:

      POST /ropledata/_search
      {
        "query" : {
          "term" : {
            "name" : "风"
          }
        }
      }
      

      运行结果如下:
      在这里插入图片描述

      所以,咱们刚才对这个疑问的解释是正确的。如果想匹配到某条数据而不想让它分词,需要使用keyword,这样对应的text就会作为一个整体来查询:

      在这里插入图片描述

    3. 便捷分词器测试技巧

      其实咱们测试分词器对词汇的分词,有一个更简便的方法,就是利用Elasticsearch的_analyze,比如咱们想看“且听风吟”被默认分词器standard分词后的效果,只需要执行如下代码:

      POST /_analyze
      {
        "analyzer":"standard",
        "text":"且听风吟"
      }
      

      运行结果如下:
      在这里插入图片描述

      这样看就更加简单直观了,咱们可以看到不同分词器对text格式数据的分词结果,感兴趣的朋友可以把所有的分词器都玩一玩。

    为了解决中文分词的问题,咱们需要掌握至少一种中文分词器,常用的中文分词器有IK、jieba、THULAC等,推荐使用IK分词器,这也是目前使用最多的分词器,接下来咱们在docker环境下把IK分词器装一下。

    三、安装IK分词器

    3.1、下载IK分词器

    下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

    打开上述网址后,根据咱们的Elasticsearch版本找到对应的编译好的包来下载,正常情况下都是有编译好的包,比如7.6.2版本的:
    在这里插入图片描述

    可是由于咱们用的是最新的7.7版本,截止到我写这篇文章的时候,7.7版本还只提供源码包,没有编译后的包:
    在这里插入图片描述
    如果你看这篇文章的时候,这里已经提供了编译后的包,请把编译好的包直接下载下来并解压,然后跳过下一小节,直接看3.3小节就可以了。如果和我一样,那就一起愉快的编译吧!

    3.2、编译源码包

    1. 下载源码包

      既然没有提供编译好的包,那么咱们就要下载源码包,自己编译了。首先把源码包下载下来,比如咱们选择zip格式的:
      在这里插入图片描述

    2. 解压并进入解压后的文件夹
      在这里插入图片描述

    3. 执行mvn编译

      在这个源码包的目录下分别执行如下命令:

      mvn clean
      mvn compile
      mvn package
      
    4. mvn编译完成后,会在elasticsearch-analysis-ik-7.7.0/target/releases目录下生成一个zip文件:
      在这里插入图片描述

    5. 解压这个zip文件,并删除原本的zip包:

      unzip elasticsearch-analysis-ik-7.4.0.zip
      rm -rf elasticsearch-analysis-ik-7.4.0.zip
      

      在这里插入图片描述

    6. 修改plugin-descriptor.properties包里的最后的Elasticsearch版本:

      vi plugin-descriptor.properties
      

      在这里插入图片描述

    7. 修改后按ESC键,并输入:wq保存退出,这时候咱们的ik插件包就准备好了,如果官网有的话,下载下来也是这样的。

    3.3、上传编译好的包到Elasticsearch

    到这里,咱们已经有编译好的包了,不管是官方提供的,还是自己编译的,都是一样的。

    1. 首先新建文件夹ik,然后把咱们下载的或者自己编译好的ik源码包里的文件都复制进去:
      在这里插入图片描述

    2. 使用docker cp命令把ik文件夹及里面的文件都上传到容器的/home/elasticsearch/elasticsearch-7.7.0/plugins/ 目录下:

      语法格式:docker cp 本地文件或文件夹路径 容器ID:容器文件或文件夹路径

       
       docker cp  ../ik a79d4cddb331:/home/elasticsearch/elasticsearch-7.7.0/plugins/
      
    3. 然后重启咱们的容器就搞定了:

      docker restart a79d4cddb331
      

    到这里,咱们已经把ik分词器插件安装成功了,下面就开始愉快的玩耍吧!

    四、玩转ik分词器

    4.1、测试ik分词器

    根据官方的建议,ik分词器的名字可以使用:ik_smart , ik_max_word
    在这里插入图片描述
    咱们可以在kibana的dev tools里执行如下代码,来测试ik分词器对中文的分词效果:

    POST /_analyze 
    {
    "analyzer": "ik_max_word",
    "text": "且听风吟" 
    }
    

    我的运行效果:
    在这里插入图片描述

    4.2、来个小案例加深理解

    下面创建一个索引,然后要求对中文部分的text用ik分词器来解析,来观察ik分词器的效果。

    1. 创建一个索引

      PUT /ropledata
      {
        "settings": {
          "index": {
            "number_of_shards": "2",
            "number_of_replicas": "0"
          }
        },
        "mappings": {
          "properties": {
            "id": {
              "type": "integer"
            },
            "name": {
              "type": "text",
              "analyzer": "ik_max_word"
            },
            "hobby": {
              "type": "text"
            }
          }
        }
      }
      
    2. 批量添加数据

      POST _bulk
      { "create" : { "_index" : "ropledata", "_id" : "1001" } }
      {"id":1,"name": "且听风吟,静待花开","hobby": "music and movie"}
      { "create" : { "_index" : "ropledata", "_id" : "1002" } }
      {"id":2,"name": "且听_风吟","hobby": "music"}
      { "create" : { "_index" : "ropledata", "_id" : "1003" } }
      {"id":3,"name": "大数据领域","hobby": "movie"}
      { "create" : { "_index" : "ropledata", "_id" : "1004" } }
      {"id":4,"name": "一起学习","hobby": "run"}
      

      在kibana里可以看到,数据已经插入成功:
      在这里插入图片描述

    3. 首先验证一下英文默认分词效果,查找hobby包含music的数据:

      POST /ropledata/_search
      {
        "query": {
          "match": {
            "hobby": "music"
          }
        }
      }
      

      在这里插入图片描述

    4. 然后验证一下中文ik分词器效果,查找name包含风吟的数据:

      POST /ropledata/_search
      {
        "query": {
          "match": {
            "name": "风吟"
          }
        }
      }
      

      在这里插入图片描述

    疑问二:ik分词器是根据什么来分词的呢?如果有些特殊的词汇比如人名,店名,网名,想根据自己的要求特殊处理来分词,能不能解决呢?

    ik分词器本身维护了一个超大的词汇文本,里面有非常多的中文词汇。这个文件在ik/config/下,名为main.dic,咱们可以打开看看:
    在这里插入图片描述
    如果要根据自己的特殊词汇来切分,咱们可以把想要切分成的词汇加入到这个文件里面就可以了。


    五、总结

    本文我们围绕Elasticsearch的分词器,从内置分词器的局限性出发,引出了中文分词器,然后详细介绍了ik分词器的编译和在docker容器环境下的安装和使用,其实在linux环境下步骤也是差不多的。不知道看完之后,大家对Elasticsearch在中文分词的学习方面有没有更进一步呢?

    如果您对我的文章感兴趣,欢迎关注点赞收藏,如果您有疑惑或发现文中有不对的地方,还请不吝赐教,非常感谢!!

  • 相关阅读:
    学习 swift (1)
    Sbulime Text 2 修改选中字符串的颜色
    js string 和 json 互转
    Mac OSX sublime text2 各种快捷键
    webstorm keymap
    python http post json
    node.js async 几个函数
    python 爬图 helloworld
    合服导致 globalserver 起不来的问题
    ssh 登陆 端口转发
  • 原文地址:https://www.cnblogs.com/-mrl/p/14255579.html
Copyright © 2020-2023  润新知