es自定义ik分词器中文词库实现热更新

        基于web地址的方式实现ik分词热更新。

操作系统:win 11

es version:8.6.2

ik version:8.6.2


1、创建web服务,并提供ik查询词库接口

  • 编写分词http url代码,返回自定义分词内容
  • 分词词库数据来自业务需求,存储于业务DB,便于维护
  • 多个分词按行输出,中文分词编码UTF-8
  • http url接口返回内容编码UTF-8
  • 设置返回header头信息 ETag 为自定义词库的hash值;
  • 设置返回header头信息 Last-Modified 为自定义词库最新更新的时间

ETag和Last-Modified任意一个变化就会ik就会更新词库。

package com.david.ikremotedict.controller;import com.david.ikremotedict.domain.IkExtDict;
import com.david.ikremotedict.domain.IkStopDict;
import com.david.ikremotedict.service.IkExtDictService;
import com.david.ikremotedict.service.IkStopDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;/*** @authar David* @Date 2025/4/1* @description*/
@Controller
@RequestMapping("/remoteDict")
public class RemoteDictController {//自定义分词词库@Autowiredprivate IkExtDictService extDictService;@Autowiredprivate IkStopDictService stopDictService;private final String DEFAULT_LAST_MODIFIED = "1743492903";/*** 扩展分词** @return *  @throws IOException*/@GetMapping(value = "extDict")@ResponseBodypublic ResponseEntity<StreamingResponseBody> ikExtDict() throws IOException {System.out.println(LocalDateTime.now());// 获取词库列表List<IkExtDict> list = extDictService.list();// 提前判断 list 是否为空,避免不必要的流式处理if (list == null || list.isEmpty()) {return ResponseEntity.noContent().header("ETag", "eb5b427b4d494525a6595a215df46dab").header("Last-Modified", DEFAULT_LAST_MODIFIED).build();}// 获取最新的创建时间戳IkExtDict latestDict = list.get(list.size() - 1);long timestamp = latestDict.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();// 创建流式响应体StreamingResponseBody responseBody = outputStream -> {try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {for (IkExtDict dict : list) {writer.write(dict.getDict());writer.newLine(); // 写入换行符}} catch (IOException exception) {exception.printStackTrace(); // 抛出异常以便上层处理}};// 返回响应实体return ResponseEntity.ok().contentType(MediaType.valueOf("text/plain;charset=UTF-8")).header("ETag", "eb5b427b4d494525a6595a215df46dab")// 这里应该返回操作dict的最后时间,先临时返回最后一个数据的创建时间.header("Last-Modified", String.valueOf(timestamp)).body(responseBody);}/*** 扩展停止词** @return *  @throws IOException*/@GetMapping(value = "stopDict")@ResponseBodypublic ResponseEntity<StreamingResponseBody> ikStopDict() throws IOException {List<IkStopDict> list = stopDictService.list();// 提前判断 list 是否为空,避免不必要的流式处理if (list == null || list.isEmpty()) {return ResponseEntity.noContent().header("ETag", "eb5b427b4d494525a6595a215df46dab").header("Last-Modified", DEFAULT_LAST_MODIFIED).build();}// 获取最新的创建时间戳IkStopDict latestDict = list.get(list.size() - 1);long timestamp = latestDict.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();// 创建流式响应体StreamingResponseBody responseBody = outputStream -> {try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {for (IkStopDict dict : list) {writer.write(dict.getDict());writer.newLine(); // 写入换行符}} catch (IOException exception) {exception.printStackTrace(); // 抛出异常以便上层处理}};// 返回响应实体return ResponseEntity.ok().contentType(MediaType.valueOf("text/plain;charset=UTF-8")).header("ETag", "5a6595a2eb5b427b4d4945215df46dab")// 这里应该返回操作dict的最后时间,先临时返回最后一个数据的创建时间.header("Last-Modified", String.valueOf(timestamp)).body(responseBody);}
}

        源码地址 github:https://github.com/a66245753/ik-remote-dict.git

        查询扩展词url:http://127.0.0.1:8080/remoteDict/extDict

        查询停用词url:http://127.0.0.1:8080/remoteDict/stopDict 

     

2、ik 插件下载配置

        2.1、下载ik分词器地址:Index of:

        2.2、进入analysis-ik

        2.3、选择es对应版本 8.6.2 

        下载地址:https://release.infinilabs.com/analysis-ik/stable/elasticsearch-analysis-ik-8.6.2.zip

         2.4、在es插件目录下新建ik目录,{es-path}\plugins\ik

         2.5、将2.3下载的压缩包解压到ik目录

          2.6、在es的config下面创建analysis-ik目录,{es-path}\config\analysis-ik

          2.7、将ik目录下config里面的文件拷贝到analysis-ik目录中

           2.8、编辑 IKAnalyzer.cfg.xml,将web服务中的数据接口地址填进去

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 --><entry key="ext_dict"></entry><!--用户可以在这里配置自己的扩展停止词字典--><entry key="ext_stopwords"></entry><!-- 用户可以在这里配置远程扩展字典  --><entry key="remote_ext_dict">http://127.0.0.1:8080/remoteDict/extDict</entry><!-- 用户可以在这里配置远程扩展停止词字典 --><entry key="remote_ext_stopwords">http://127.0.0.1:8080/remoteDict/stopDict</entry>
</properties>

3、启动es和kibana

        启动es的时候会看到加载plugin的日志和词库内容。

4、验证 

        4.1、没加“噜咪啦”分词前的解析

        4.2、加“噜咪啦”分词后的解析 

 经过测试ik读取web地址的频率是每分钟一次,暂时没找到强制刷新的方法。

索引字段与属性都属于静态设置,若后期变更历史数据需要重建索引才可生效
对历史数据无效!!!!一定要重建索引!!!!

重建索引:es 3期 第10节 如何正确使用Reindex重建索引_es reindex 原索更新正常使用-CSDN博客

配置文件含义:

IKAnalyzer.cfg.xml:配置自定义词库文件

main.dic:内置的中文词库

quantifier.dic:单位相关的词

suffix.dic:后缀词

surname.dic:中国姓氏

stopword.dic:英文停用词

preposition.dic:介词词典

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

铂卡梭 智能羽翼 AI 系统:交易科技的未来引擎

突破性的 AI 交易系统 铂卡梭(Pegasus)近期推出的 InnoFeather AI System(智能羽翼 AI 系统) 代表了金融科技领域的前沿突破。这一系统集成了先进的 机器学习算法、大数据分析 和 实时市场情绪感知,旨在帮助交易者在复杂多变的市场环境中做出更精准的决策。 智能羽翼 AI 系统的…

js中判断对象是否包含某个属性(元素)

在JavaScript中&#xff0c;判断对象是否包含某个属性&#xff08;元素&#xff09;主要有以下几种方法&#xff0c;根据具体需求选择合适的方式&#xff1a; 1. 使用 in 运算符 作用&#xff1a;检查对象自身及原型链上是否存在指定属性。 示例&#xff1a; javascript cons…

Anaconda和Pycharm的区别,以及如何选择两者

目录 主要区别详细说明如何选择&#xff1f;Anaconda的使用步骤 主要区别 Anaconda 和 PyCharm 是 Python 开发中常用的两个工具&#xff0c;但它们的定位和功能完全不同。以下是它们的主要区别&#xff1a; 对比项AnacondaPyCharm类型Python 发行版 包管理工具Python 集成开…

UE小:在Unreal Engine 5中实现多层静态网格体遮挡拾取

问题描述 当需要拾取被多层静态网格体遮挡的对象时&#xff0c;若所有网格体碰撞预设为BlockAll&#xff0c;需要通过特殊配置实现穿透检测。 完整实现方案 1. 创建自定义追踪通道 进入 ​项目设置&#xff08;Project Settings&#xff09; > 碰撞&#xff08;Collision…

wireshark抓包分析数据怎么看 wireshark使用教程_wireshark怎么看

Wireshark与Sniff Master&#xff1a;网络抓包工具使用指南 网络抓包分析是开发测试和网络故障排查中不可或缺的技能。在众多抓包工具中&#xff0c;Wireshark无疑是最流行且功能强大的选择&#xff0c;而Sniff Master作为后起之秀&#xff0c;也因其简洁高效的特点受到许多专…

密码学基础——古典密码学

目录 一、定义 特点&#xff1a; 二、发展阶段 三、代换密码 1.单表代换密码 1.1恺撒密码 1.2 移位变换 1.3 仿射变换 2.多表代换密码 维吉尼亚密码 四、置换密码 栅栏密码 一、定义 古典密码学是指在现代密码学出现之前&#xff0c;使用较为简单的数学方法和手工…

【案例分享】江苏某汽车制造厂水冷式制冷站AI节能优化方案

主要诉求&#xff1a; 对B系统进行AI节能优化&#xff1a;3台离心机1台螺杆机板式换热器 优化前后对比&#xff1a; ⚫ 优化前&#xff1a;根据人工经验判断冷机和板换的启停&#xff0c;PLC固定逻辑调节参数 ⚫优化后&#xff1a;根据冷负荷对工况进行分类&#xff0c;自动…

vue+springboot 新增操作,前端id传string,后端接收为long类型,报错类型不匹配——解决方法

我在做新增功能的时候&#xff0c;做了一个逻辑判断&#xff0c;当前端没有传递对应的id值时&#xff0c;为新增&#xff1b;有id值时&#xff0c;为修改 问题一、&#xff1a;前端idundefined&#xff0c;和我的需求不符合&#xff0c;我要id为空&#xff0c;不传值。最后发现…

vue前端项目技术架构(第二版)

vue技术架构介绍 如下图所示&#xff0c;展示了项目系统的软件层次架构。该系统采用基于SOA&#xff08;面向服务架构&#xff09;思想的分层架构&#xff0c;分为四个主要层次&#xff1a;视图层、编译层、代码层和数据层。 视图层 浏览器&#xff1a;核心职责是解析并展示…

在服务器里面磁盘分区很简单吗?

不管是我们的普通办公电脑还是服务器都是需要硬盘的&#xff0c;硬盘的类型分机械硬盘&#xff08;HDD&#xff09;和固态硬盘&#xff08;SSD&#xff09;&#xff0c;这两种磁盘是我们平常最常见的硬盘您他们又有什么区别 机械硬盘&#xff08;HDD&#xff09; 原理&#xff…

Pycharm(十一):字符串练习题

1.输入一个字符串&#xff0c;打印所有偶数位上的字符(下标是0&#xff0c;2&#xff0c;4&#xff0c;6...位上的字符) # 练习题1:输入一个字符串&#xff0c;打印所有偶数位上的字符(下标是0&#xff0c;2&#xff0c;4&#xff0c;6...位上的字符) # 1.键盘录入字符串&…

虚幻5入门

常用操作 运行时&#xff0c;调试相机&#xff0c;按~键&#xff0c;输入ToggleDebugCamera 。进入自由视角 常用节点 gate节点&#xff1a;用于控制该流程通不通&#xff0c;执不执行。Flip Flop节点&#xff1a;反转执行&#xff0c;一次A&#xff0c;一次B。Set Timer by…

Prompt Flow 与 DSPy:大型语言模型开发的未来

作为一名大模型算法工程师&#xff0c;我一直在探索如何更高效地开发和优化基于大型语言模型&#xff08;LLM&#xff09;的应用程序。随着模型规模的不断扩大和应用场景的日益复杂&#xff0c;传统的开发方式已经难以满足高效、灵活和可扩展的需求。幸运的是&#xff0c;Promp…

Prompt攻击是什么

什么是Prompt攻击 Prompt攻击(Prompt Injection/Attack) 是指通过精心构造的输入提示(Prompt),诱导大语言模型(LLM)突破预设安全限制、泄露敏感信息或执行恶意操作的攻击行为。其本质是利用模型对自然语言的理解漏洞,通过语义欺骗绕过防护机制。 Prompt攻击的精髓:学…

Python 数据类型 - 集合(set)

Python 数据类型 - 集合(set) 1. 集合简介 集合(set)是Python中的一种无序、可变、不重复元素的容器数据类型。集合的主要用途&#xff1a; 快速成员检测&#xff08;判断元素是否存在&#xff09;去除重复项执行数学集合运算&#xff08;并集、交集、差集等&#xff09; 2.…

Profibus DP主站转Modbus TCP网关配置文件制作

Profibus DP主站转Modbus TCP网关配置文件制作 1、首先打开配置文件制作软件SST Profibus Configuration&#xff1a; 2、点击“Library”选择GSD文件所在文件夹找到后点击打开导入GSD文件: 3、点开Masters、molex选择主站设备&#xff1a; 4、双击添加后地址保存默认0就可以&…

如何批量拆分Excel工作表或按行拆分Excel表格 - Excel拆分器使用方法

在数据分析和处理的日常工作中&#xff0c;Excel文件因其强大的数据管理和计算能力而广受欢迎。然而&#xff0c;当面对庞大的Excel工作簿&#xff0c;特别是需要将其拆分为多个独立文件时&#xff0c;传统的操作方法往往会显得繁琐且效率低下。为了解决这一难题&#xff0c;Ex…

JavaScript基础-移动端常见特效

随着移动互联网的发展&#xff0c;为移动设备优化的网页变得越来越重要。JavaScript在实现移动端特有的交互体验中扮演着关键角色。本文将介绍几种常见的移动端特效&#xff0c;并通过具体的代码示例展示如何使用JavaScript和相关技术来创建这些特效。 一、手势识别 &#xf…

ui-tars和omni-parser使用

ui-tars部署和训练 说明快速开始环境准备ui-tars web推理和训练ui-tars api部署omni-parser使用 说明 镜像中包含ui-tars、llama-factory和omni-parser。该镜像还在审批中&#xff0c;估计明天可以上线&#xff0c;到时候可以在auto-dl中的社区镜像搜索。 快速开始 使用auto…

TF-IDF——自然语言处理——红楼梦案例

目录 一、红楼梦数据分析 &#xff08;1&#xff09;红楼梦源文件 &#xff08;2&#xff09;数据预处理——分卷实现思路 &#xff08;3&#xff09;分卷代码 二、分卷处理&#xff0c;删除停用词&#xff0c;将文章转换为标准格式 1.实现的思路及细节 2.代码实现&#…