2023-02-06 Elasticsearch 分词器相关

分词器是es中的一个组件,通俗意义上理解,就是将一段文本按照一定的逻辑,分析成多个词语,同时对这些词语进行常规化的一种工具;ES会将text格式的字段按照分词器进行分词,并编排成倒排索引,正是因为如此,es的查询才如此之快;
在这里插入图片描述

1 normalization 规范化

在这里插入图片描述

2 character filter 字符过滤器

分词之前的预处理,过滤无用字符

2.1 HTML Strip

在这里插入图片描述

PUT /define_index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "define_char_filter": {
          "type": "html_strip"
        }
      },
      "analyzer": {
        "define_analyzer": {
          "tokenizer": "keyword",
          "char_filter": [
            "define_char_filter"
          ]
        }
      }
    }
  }
}

自定义字符过滤器define_analyzer,作用是过滤数据中的html标签

GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["<p>I; m so <a>happy</a></p>"]
}

在这里插入图片描述
可使用"escaped_tags":[“a”]设置保留不被过滤的标签
在这里插入图片描述

2.2 Mapping

PUT /define_index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "define_char_filter": {
          "type": "mapping",
          "mappings": ["滚 => *", "垃圾 => 可爱"]
        }
      },
      "analyzer": {
        "define_analyzer": {
          "tokenizer": "keyword",
          "char_filter": [
            "define_char_filter"
          ]
        }
      }
    }
  }
}

GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["<p>你好啊 你这个大垃圾, 滚犊子"]
}

在这里插入图片描述
通过自定义的过滤器,可以将聊天、留言或者弹幕之类的发言根据需求进行屏蔽或替换。

2.3 Pattern Replace

PUT /define_index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "define_char_filter": {
          "type": "pattern_replace",
          "pattern": "(\\d{3})\\d{4}(\\d{4})",
          "replacement": "$1****$2"
        }
      },
      "analyzer": {
        "define_analyzer": {
          "tokenizer": "keyword",
          "char_filter": [
            "define_char_filter"
          ]
        }
      }
    }
  }
}

GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["电话号码:13792223536"]
}

在这里插入图片描述
通过正则表达式进行数据的替换。

3 token filter 令牌过滤器

停用词、时态转换、大小写转换、同义词转换、语气词处理等。

PUT /define_index
{
  "settings": {
    "analysis": {
      "filter": {
        "define_synonym": {
          "type": "synonym",
          "synonyms": [
            "东邪 => 黄药师",
            "西毒 => 欧阳锋",
            "南帝 => 段智兴",
            "北丐 => 洪七公"]
        }
      },
      "analyzer": {
        "define_analyzer": {
          "tokenizer": "standard",
          "filter": ["define_synonym"]
        }
      }
    }
  }
}

GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["东邪", "西毒"]
}

在这里插入图片描述
可以看到"东邪"检索到"黄药师"的分词,"西毒"检索到"欧阳锋"的分词。
除了自定义的以外,也可以使用ES自带的,比如大小写的转换:
在这里插入图片描述
在这里插入图片描述
甚至可以通过自定义脚本动态的控制过滤逻辑,比如将长度小于5的字符串转为全大写:

GET /define_index/_analyze
{
  "tokenizer": "standard",
  "filter": {
    "type": "condition",
    "filter": "uppercase",
    "script": {
      "source": "token.getTerm().length() < 5"
    }
  },
  "text": ["FeeNIXee IanlXD DOc dkkkk kkk ddd ds"]
}

在这里插入图片描述
也可以将一些语句中没有什么意义的语气词等作为停用词不参与检索:

PUT /define_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "define_analyzer": {
          "type": "standard",
          "stopwords": "_english_"
        }
      }
    }
  }
}


GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["FeeNIXee IanlXD DOc and is or ds"]
}

在这里插入图片描述
也可以将一些语句中不管有没有意义所有的词都不作为停用词参与检索:

PUT /define_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "define_analyzer": {
          "type": "standard",
          "stopwords": "_none_"
        }
      }
    }
  }
}


GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["FeeNIXee IanlXD DOc and is or ds"]
}

在这里插入图片描述
当然也可以手动自定义去设置那些词作为停用词使用:

PUT /define_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "define_analyzer": {
          "type": "standard",
          "stopwords": ["is", "or", "ds"]
        }
      }
    }
  }
}


GET /define_index/_analyze
{
  "analyzer": "define_analyzer",
  "text": ["FeeNIXee IanlXD DOc and is or ds"]
}

在这里插入图片描述

4 tokenizer 分词器

在这里插入图片描述
但是对于中文来说,standard也是非常简单粗暴的按照每一个汉字来进行切割,这就很难受了:
在这里插入图片描述
虽然ES官方提供了很多个分词器,其实对于中文的支持都不好用:

standard:默认分词器,中文会逐字拆分;

pattern:以正则匹配分隔符,把文本拆分成若干词项;

simple pattern:以正则匹配词项,速度比pattern会快一些;

whitespace:以空白符分隔,把文本拆分成若干词项;

既然官方提供的不好用,那就得自己手动来自定义分词器:

char_filter:内置或自定义字符过滤器;

token_filter:内置或自定义token过滤器;

tokenizer:内置或自定义分词器;

在这里插入图片描述

值得一提的是my_tokenizer的设置,“pattern”: "[,.!;?]"指的是文本会按照[]中有的符号去切割

4.1 ES安装IK分词器

https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.0/elasticsearch-analysis-ik-7.10.0.zip
在这里插入图片描述
解压IK分词器安装包,重启ES服务

GET /define_index/_analyze
{
  "analyzer": "ik_max_word",
  "text": ["我爱中文,你是中国人吗"]
}

在这里插入图片描述
IK文件描述
IKAnalyzer.cfg.xml:IK分词器配置文件
在这里插入图片描述
main.dic:IK分词器主词库,也是IK最大的词库,收录了20多万常用的汉语词汇

在这里插入图片描述
stopword.dic:英文停用词库,不会建立在倒排索引中

在这里插入图片描述
quantifier.dic:特殊词库,计量单位

在这里插入图片描述
suffix.dic:特殊词库,行政、地理单位

在这里插入图片描述
surname.dic:特殊词库,百家姓

在这里插入图片描述
preposition.dic:特殊词库,语气词

在这里插入图片描述
根据IK分词器官方提供的文档,提供了两个analyzer和两个tokenizer,都是ik_smart和ik_max_word。
在这里插入图片描述
在这里插入图片描述
在官方词库中没有 蒙丢丢 如下所示,被拆分了
在这里插入图片描述
我们可以修改配置文件来解决问题

在这里插入图片描述
调整文件:
在这里插入图片描述
新建文档
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5 热更新

5.1 基于远程词库的热更新

每次在修改完IK分词器的配置文件之后,都需要对ES服务进行重新启动。

现在每天网络热门词汇层出不穷,按照词汇更新的速度频率经常重启ES服务显示是不可能的。在新版本中,IK分词器官方可以支持配置远程扩展字典和扩展停止词字典:
在这里插入图片描述
并且官方也提供了非常详细的使用步骤说明:
在这里插入图片描述

package com.inspur.elasticsearch.controller;

import lombok.val;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * IK热更新控制器
 *
 * @author zhaoshuai-lc
 * @date 2023/02/07
 */
@RestController
@RequestMapping(value = "/api")
public class HotUpdateController {
    /**
     * type - 0
     */
    private static final Integer HOT_WORD = 0;

    /**
     * 刷新词库
     *
     * @param type     词库类型
     * @param response 响应
     */
    @RequestMapping(value = "/refreshThesaurus")
    public void refreshThesaurus(HttpServletResponse response, Integer type) {
        try {
            val path = HOT_WORD.equals(type) ? "src/main/resources/hotUpdateWord/hotWord.dic" :
                    "src/main/resources/hotUpdateWord/stopWord.dic";
            val file = new File(path);
            val fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[(int) file.length()];

            int offset = 0;
            while (-1 != fileInputStream.read(buffer, offset, buffer.length - offset)) {

            }
            response.setHeader("Last-Modified", String.valueOf(buffer.length));
            response.setHeader("ETag", String.valueOf(buffer.length));
            response.setContentType("text/plain;charset=utf-8");

            val outputStream = response.getOutputStream();
            outputStream.write(buffer);
            outputStream.flush();
            outputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

nginx的相关知识补充,不然不会起作用

5.2 基于MySQL数据库的热更新

https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.8.0

https://blog.csdn.net/qq_24223159/article/details/124691360

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值