当前位置: 首页 > news >正文

基于 Elasticsearch 8.12.0 集群热词实现

前言

在当今信息爆炸的时代,数据如同潮水般汹涌而来,海量的信息充斥着我们的生活与工作。无论是社交媒体上的热门话题,电商平台上的流行商品,还是新闻资讯中的焦点事件,热词的出现频率与传播速度都成为了衡量其重要性与影响力的关键指标。而 Elasticsearch(简称 ES)作为一款功能强大的搜索引擎与数据分析工具,以其卓越的性能、灵活的架构以及强大的文本处理能力,成为了众多企业和开发者在数据管理和检索领域的首选利器。
热词,作为数据海洋中的“灯塔”,能够快速引导我们发现用户关注的焦点、市场的趋势以及潜在的热点问题。然而,如何从海量的数据中精准地提取热词,并实时地呈现其热度变化,这不仅是一项技术挑战,更是一场对数据价值挖掘的深度探索。Elasticsearch 提供了丰富的工具和功能,从文本分析到聚合查询,从实时索引到高效的搜索性能,为实现热词的高效提取与展示提供了坚实的基础。

安装分词器

分词器
HanLP(Han Language Processing)是一个针对中文优化的自然语言处理库,提供了包括词法分析、句法分析、命名实体识别等多种NLP功能。

<dependency><groupId>com.hankcs</groupId><artifactId>hanlp</artifactId><version>portable-1.8.6</version>
</dependency>

使用

natures 定义详见附录:重点关注词性分类表

import cn.hutool.core.util.ArrayUtil;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;
import lombok.extern.slf4j.Slf4j;import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;/*** 功能描述** @author jason*/
@Slf4j
public class HanlpUtil {/*** 获取分词*/public static Set<String> getWordSet(String text) {String[] natures = {"n", "nr", "nrj", "ns", "nt", "nz", "nh", "nm", "nf", "j", "i", "l", "vn", "ad", "nx", "xx"};List<Term> termList = HanLP.segment(text);for (Term term : termList) {log.info(term.word + " - " + term.nature);}Set<String> wordSet = termList.stream().filter(term -> ArrayUtil.contains(natures, term.nature.toString())).map(term -> term.word).collect(Collectors.toSet());log.info("分词:{}", wordSet);return wordSet;}public static void main(String[] args) {// 输入字符串String text = "HanLP 是一个自然语言处理工具包。是一个面向生产环境的多语种自然语言处理工具包,它基于PyTorch和TensorFlow 2.x双引擎,目标是普及落地最前沿的NLP技术\n" +"无论您是专家还是初学者,HanLP都可以让您能够轻松快速的构建、处理和“理解”大量文本的AI应用程序";Set<String> wordSet = getWordSet(text);log.info("分词:{}", wordSet);}}

输出

16:08:04.297 [main] INFO org.example.es.util.HanlpUtil -- HanLP - nx
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil --   - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 是 - vshi
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 一个 - mq
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 自然语言处理 - nz
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 工具包 - n
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 。 - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 是 - vshi
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 一个 - mq
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 面向 - v
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 生产 - vn
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 环境 - n
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 的 - ude1
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 多 - a
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 语种 - n
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 自然语言处理 - nz
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 工具包 - n
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- , - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 它 - rr
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 基于 - p
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- PyTorch - nx
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 和 - cc
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- TensorFlow - nx
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil --   - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 2 - m
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- . - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- x - nx
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 双引擎 - b
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- , - w
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 目标 - n
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 是 - vshi
16:08:04.299 [main] INFO org.example.es.util.HanlpUtil -- 普及 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 落地 - vi
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 最 - d
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 前沿 - s
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 的 - ude1
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- NLP - nx
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 技术 - n
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- - w
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 无论 - c
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 您 - rr
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 是 - vshi
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 专家 - nnt
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 还是 - c
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 初学者 - n
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- , - w
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- HanLP - nx
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 都 - d
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 可以 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 让 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 您 - rr
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 能够 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 轻松 - a
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 快速 - d
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 的 - ude1
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 构建 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 、 - w
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 处理 - vn
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 和 - cc
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- “ - w
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 理解 - v
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- ” - w
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 大量 - m
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 文本 - n
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 的 - ude1
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- AI - nx
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 应用 - vn
16:08:04.300 [main] INFO org.example.es.util.HanlpUtil -- 程序 - n
16:08:04.306 [main] INFO org.example.es.util.HanlpUtil -- 分词:[技术, 初学者, 生产, AI, 处理, 文本, 程序, 语种, PyTorch, NLP, 目标, x, 工具包, 自然语言处理, 环境, HanLP, TensorFlow, 应用]

热词排行榜

@Data
@AllArgsConstructor
public class RankingEntry {/*** 热词*/private String word;/*** 出现的数量*/private int num;}
import cn.hutool.core.collection.CollectionUtil;
import org.example.es.entity.EsProduct;
import org.example.es.util.HanlpUtil;import java.util.*;/*** 自定义排行榜类-仅用于测试** 实际产线环境,需要结合 Redis 实现*/
public class RankingClient {private static final Map<String, Integer> rankMap = new HashMap<>();/*** 批量新增热词*/public synchronized static void batchAddWord(List<EsProduct> productList) {for (EsProduct esProduct : productList) {Set<String> wordSet = HanlpUtil.getWordSet(esProduct.getDescription());for (String word : wordSet) {addOrUpdateWord(word, 1);}}}/*** 新增计数或更新计数*/public synchronized static void addOrUpdateWord(String word, int num) {int rankNum = rankMap.getOrDefault(word, 0);rankMap.put(word, rankNum + num);}/*** 获取完整排行榜*/public static List<RankingEntry> getRanking() {List<RankingEntry> rankList = new ArrayList<>();rankMap.forEach((word, num) -> rankList.add(new RankingEntry(word, num)));CollectionUtil.sort(rankList, Comparator.comparingInt(RankingEntry::getNum).reversed());return rankList;}/*** 获取前 n 名*/public static List<RankingEntry> getTopN(int n) {return CollectionUtil.sub(getRanking(), 0, n);}/*** 清空排行榜*/public static void clear() {rankMap.clear();}public static void main(String[] args) {// 添加测试数据RankingClient.addOrUpdateWord("Alice", 10);RankingClient.addOrUpdateWord("Bob", 5);RankingClient.addOrUpdateWord("Charlie", 15);RankingClient.addOrUpdateWord("Alice", 3); // Alice已有记录,会增加次数// 获取完整排行榜System.out.println("完整排行榜:");List<RankingEntry> fullRanking = RankingClient.getRanking();for (RankingEntry entry : fullRanking) {System.out.println(entry);}// 获取前2名System.out.println("\nTop 2:");List<RankingEntry> top2 = RankingClient.getTopN(2);for (RankingEntry entry : top2) {System.out.println(entry);}}}

使用

    @GetMapping("/searchByMatch/{index}")public List<EsProduct> searchByMatch(@PathVariable String index, @RequestParam String keyword) {BoolQuery boolQuery = new BoolQuery.Builder().should(s -> s.match(m -> m.field("name").query(keyword))).should(s -> s.match(m -> m.field("description").query(keyword))).should(s -> s.match(m -> m.field("category").query(keyword))).build();List<EsProduct> esProductList = esClient.searchByBool(index, EsProduct.class, boolQuery);// 热词RankingClient.batchAddWord(esProductList);return esProductList;}
    @GetMapping("/hotWords")public List<RankingEntry> hotWords() {return RankingClient.getRanking();}

测试

http://127.0.0.1:9200/es/product/hotWords
[{"word": "防水","num": 46},{"word": "防尘","num": 46},{"word": "续航","num": 34},{"word": "设计","num": 32},{"word": "电池","num": 20},{"word": "vivo","num": 20},{"word": "容量","num": 20},{"word": "iQOO","num": 16},{"word": "OPPO","num": 14}
]

搜索多个品牌,然后多搜索几次小米
在这里插入图片描述
最终热词榜结果
在这里插入图片描述

附:热词分析 - 重点关注词性分类表

主要关注词性(核心热词)

词性标记类别说明示例
n普通名词一般事物名词手机、电脑、天气
nr人名中文人名张三、李四
nrj日语人名日语姓名山田、佐藤
ns地名地理名称北京、上海
nt机构团体名公司、组织、机构名称腾讯、联合国
nz其他专名未归类专有名词ChatGPT、元宇宙
nh医药名词药品、疾病、医学术语阿司匹林、糖尿病
nm物品名词具体物品名称手机、汽车
nf食品名词食物、饮料相关名词咖啡、披萨
j简称略语缩写、简称5G、AI
i成语四字成语或固定短语亡羊补牢、守株待兔
l习用语常用固定搭配一言难尽、不可思议
v普通动词动作、行为跑步、学习
vn名动词可作名词的动词研究、调查
a形容词描述性词汇漂亮、聪明
ad副形词可作副词的形容词快速、直接
nx外文字符英文、数字、符号等iPhone、2024
xx非语素字网络新词、特殊符号绝绝子、yyds

次要关注词性(特定场景下可能有用)

词性标记类别说明示例
nbaNBA相关词篮球术语、球队、球员湖人、詹姆斯
nbc生物名词动植物、生物学术语熊猫、DNA
t时间词时间相关词汇今天、2025年
tg时间词性语素时间相关的构词语素年、月、日

总结建议

  • 核心热词:优先关注名词类(n系列)、简称(j)、成语(i)、动词(v/vn)、形容词(a/ad)以及外文/网络词(nx/xx)
  • 特定领域:根据分析目标选择性关注体育(nba)、生物(nbc)、时间(t/tg)等词性
  • 可忽略词性:助词(u)、连词(c)、标点(w)等对热词分析价值较低

提示:实际分析时可结合词频统计和上下文关联度进一步筛选有价值的热词

相关文章:

  • Hello, Dirty page
  • LabVIEW发电机励磁系统远程诊断
  • P8512 [Ynoi Easy Round 2021] TEST_152 Solution
  • conda环境独立管理cudatoolkit
  • vulnhub five86系列靶机合集
  • HTTP:十.cookie机制
  • 2000-2017年各省城市液化石油气供气总量数据
  • 硬件工程师笔记——电子器件汇总大全
  • HTML — 总结
  • LeetCode[225]用队列实现栈
  • LeetCode 每日一题 2563. 统计公平数对的数目
  • WEMOS LOLIN32
  • python之计算平面曲线离散点的曲率
  • vivo把三颗「主摄」放进了手机
  • cpp知识章节
  • SpringAI系列 - MCP篇(一) - 什么是MCP
  • VitePress搭建-接入giscus的注意事项。
  • 第十章 继承与派生
  • PCL库开发入门
  • 【C++】win 10 / win 11:Dev-C++ 下载与安装
  • 上海开展2025年“人民城市 文明风采”群众性主题活动
  • 东阿至聊城公交票价取消八折优惠:运行成本高昂
  • 科普|结石疼痛背后的危机信号:疼痛消失≠警报解除
  • 吉林省委原书记、吉林省人大常委会原主任何竹康逝世
  • AI时代的阅读——当今时代呼唤文学的思想实验和人文认知
  • 门票在“缩水”,古镇怎么办