写的一款简易的热点词汇记录工具

news2025/1/12 13:18:21

项目需要对用户提交的附件、文章、搜索框内容等做热词分析。如下图:
在这里插入图片描述
公司有大数据团队。本着不麻烦别人就不麻烦别人的原则,写了一款简易的记录工具,原理也简单,手工在业务插入锚点,用分词器分好词,排掉字母、数字、符号、敏感词。将词汇按年度累加记录到数据库中即可。代码如下:

@Component
public class HotWordHelper {

    private static HotWordMapper hotWordMapper;

    static List<Character> FILTER_CHARS = new ArrayList<>();

    static {
        String number = "123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ";
        char[] chars = number.toCharArray();
        for (char aChar : chars) {
            FILTER_CHARS.add(aChar);
        }
    }

    @Autowired
    public ZYHotWordHelper(HotWordMapper hotWordMapper) {
        ZYHotWordHelper.hotWordMapper = hotWordMapper;
    }

    public static List<HotWord> loaderHotWordTen(String moduleCode) {
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        return loaderHotWord(year, 10, moduleCode);
    }

    public static List<HotWord> loaderHotWord(int top, String moduleCode) {
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        return loaderHotWord(year, top, moduleCode);
    }

    public static List<HotWord> loaderHotWord(int year, int top, String moduleCode) {
        LambdaQueryWrapper<HotWord> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(HotWord::getRecordYear, year);
        wrapper.eq(HotWord::getModuleCode, moduleCode);
        return hotWordMapper.selectTop(wrapper, HotWord::getAppearTimes, top);
    }

	// 直接词汇,如字典之类的。
    public static void putDirectHotWord(String text, String moduleCode) {
    	// 为不影响主业务速度,改成异常
        Runnable runnable = () -> putHotWord(true, text, moduleCode);
        AsyncExecutor.execute(runnable);
    }
	
	// 分析词汇
    public static void putAnalyzeHotWord(String text, String moduleCode) {
    	// 为不影响主业务速度,改成异常
        Runnable runnable = () -> putHotWord(false, text, moduleCode);
        AsyncExecutor.execute(runnable);
    }

	// 附件
    public static void putAttachmentAsync(StringsField attachmentIds, String moduleCode) {
        if (ZYListUtils.isEmptyList(attachmentIds)) {
            return;
        }
        Runnable runnable = () -> doPutAttachmentAsync(attachmentIds, moduleCode);
        AsyncExecutor.execute(runnable);
    }

	// 解析附件
    private static void doPutAttachmentAsync(StringsField attachmentIds, String moduleCode) {
        FileInfoMapper fileInfoMapper = SpringUtils.getBean(FileInfoMapper.class);
        List<FileInfo> fileInfos = fileInfoMapper.selectBatchIds(attachmentIds);
        if (ZYListUtils.isEmptyList(fileInfos)) {
            return;
        }

        FileStoreService storeService= ZYSpringUtils.getBean(FileStoreService.class);
        List<FileWrapper> fileWrappers = ZYListUtils.list2list(fileInfos, FileInfo::toFileWrapper);
        for (FileWrapper fileWrapper : fileWrappers) {
            try (InputStream objectStream = storeService.getObjectStream(fileWrapper)) {
                String text = IOUtils.toString(objectStream, StandardCharsets.UTF_8);
                putAnalyzeHotWord(text, moduleCode);
            } catch (Exception e) {
                return;
            }

        }
    }

    private static void putHotWord(boolean isDirect, String text, String moduleCode) {
        if (ZYStrUtils.isAnyNull(text, moduleCode)) {
            return;
        }

        List<String> words = analyzerWords(isDirect, text);
        if (ZYListUtils.isEmptyList(words)) {
            return;
        }
        //  List<String> smallWordCompare = new ArrayList<>(words);
        words.removeIf(w -> {
            if (!matchLength(w)) {
                return true;
            }
            char[] chars = w.toCharArray();
            for (char aChar : chars) {
                // 不要数字字母
                if (FILTER_CHARS.contains(aChar)) {
                    return true;
                }
            }

            // 存在误判,还是不用这段代码
      /*      for (String compareWord : smallWordCompare) {
                if (!w.equals(compareWord) && compareWord.contains(w)) {
                    return true;
                }
            }
*/
            return false;
        });
        Map<String, Integer> wordCount = ZYMapUtils.countField(words, w -> w);

        LocalDate now = LocalDate.now();
        int year = now.getYear();
        LambdaQueryWrapper<HotWord> wrapper = Wrappers.lambdaQuery();
        wrapper.in(HotWord::getHotWord, words);
        wrapper.eq(HotWord::getRecordYear, year);
        wrapper.eq(HotWord::getModuleCode, moduleCode);
        List<HotWord> existsWords = hotWordMapper.selectList(wrapper);
        Map<String, HotWord> wordIdContainer = ZYListUtils.groupModel(existsWords, HotWord::getHotWord);

        List<HotWord> addHotWords = new ArrayList<>();
        List<HotWord> editHotWords = new ArrayList<>();
        wordCount.forEach((w, times) -> {
            HotWord hotWord = wordIdContainer.get(w);
            if (null != hotWord) {
                Integer appearTimes = hotWord.getAppearTimes();
                appearTimes += times;
                hotWord.setAppearTimes(appearTimes);
                editHotWords.add(hotWord);
            } else {
                HotWord newHotWord = new HotWord();
                newHotWord.setRecordYear(year);
                newHotWord.setAppearTimes(times);
                newHotWord.setHotWord(w);
                newHotWord.setModuleCode(moduleCode);
                addHotWords.add(newHotWord);
            }
        });

        if (ZYListUtils.isNotEmptyList(addHotWords)) {
            hotWordMapper.insertBatch(addHotWords);
        }
        if (ZYListUtils.isNotEmptyList(editHotWords)) {
            for (HotWord editHotWord : editHotWords) {
                hotWordMapper.updateById(editHotWord);
            }
        }
    }

    private static List<String> analyzerWords(boolean isDirect, String text) {
        List<String> words;
        if (isDirect) {
            words = Collections.singletonList(text);
        } else {
            words = ZYDirtyWordHelper.analyze(text);
            if (matchLength(text) && !words.contains(text)) {
                words.add(text);
            }
        }
        return words;
    }
    
    private static boolean matchLength(String text) {
        int length = text.length();
        return length > 1 && length < 6;
    }

}

记录表中效果图,实际效果还阔以,实时性和记录速度都非常快。
在这里插入图片描述

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

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

相关文章

阿晨的运维笔记 | CentOS部署Docker

使用yum安装 # step 1: 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # Step 2: 添加软件源信息 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # Step 3: 更新并安装 …

使用VBA快速关闭应用程序进程

使用VBA进行开发时&#xff0c;如果需要关闭其他Office应用程序&#xff0c;那么通常可以使用GetObject的方式获取该应用程序的引用&#xff0c;然后再关闭&#xff0c;有时需要重复多次以关闭多进程。如果希望关闭的应用程序并非Office组件&#xff0c;那么GetObject方式有时就…

裸露土方智能识别算法 python

裸露土方智能识别算法通过opencvpython网络模型框架算法&#xff0c;裸露土方智能识别算法能够准确识别现场土堆的裸露情况&#xff0c;并对超过40%部分裸露的土堆进行抓拍预警。此次算法用到的Python是一种由Guido van Rossum开发的通用编程语言&#xff0c;它很快就变得非常流…

NOR型flash vs NAND型flash

FLASH是一种存储芯片&#xff0c;全名叫Flash EEPROM Memory&#xff0c;通过程序可以修改数据&#xff0c;即平时所说的“闪存”。 闪存可以在软件的控制下写入和擦写数据。其存储空间被分割成相对较大的可擦除单元&#xff0c;成为擦除块&#xff08;erase block&#xff09…

嵌入式岗位笔试面试专栏 - 岗位介绍

文章目录 一、嵌入式岗位的分类二、热门领域及公司三、发展前景四、技能要求沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将讲解嵌入岗位的工作职责 。 一、嵌入式岗位的分类 嵌入式软件工程师大致可以分为两种类型: 应用开发工程师驱动开发工程师应用工程…

【炼气境】HashMap原理以及如何使用

系列文章目录 文章目录 系列文章目录前言1、数据结构2、工作原理3、当两个对象的 hashCode 相同会发生什么&#xff1f;4、你知道 hash 的实现吗&#xff1f;为什么要这样实现&#xff1f;5、为什么要用异或运算符&#xff1f;6、HashMap 的 table 的容量如何确定&#xff1f;l…

PHP8内置函数中的变量函数-PHP8知识详解

在php8中&#xff0c;与变量相关的内置函数比较多&#xff0c;本文说一些比较重要的、常见的内置函数。今日着重讲解了5个&#xff0c;分别是&#xff1a;检测变量是否为空的函数empty()、判断变量是否定义过的函数isset()、销毁指定的变量的函数unset()、获取变量的类型的函数…

【力扣周赛】第 359 场周赛(选择区间型DP⭐⭐⭐⭐⭐新题型 双指针)

文章目录 竞赛链接Q1&#xff1a;7004. 判别首字母缩略词&#xff08;模拟&#xff09;Q2&#xff1a;6450. k-avoiding 数组的最小总和解法1——贪心哈希表解法2——数学公式 Q3&#xff1a;7006. 销售利润最大化⭐⭐⭐线性DP相似题目列表2008. 出租车的最大盈利&#xff08;和…

2023.9.1 简单认识 JVM

目录 JVM 内存划分 本地方法栈 虚拟机栈 程序计数器 堆区 元数据区 JVM 类加载机制 加载 验证 准备 解析 初始化 类被加载的几种情况&#xff08;懒汉模式 ---> 只要被用到才会被加载&#xff09; 双亲委派模型 JVM 内存划分 JVM 是一个应用程序&#xff0c;在…

SSM(Spring-Mybatis-SpringMVC)

文章目录 1. 介绍1.1 概念介绍 2 SSM整合框架3. SSM功能模块开发4 测试4.1 业务层接口测试4.2 表现层接口测试 5.优化 -表现层数据封装6.异常处理 1. 介绍 1.1 概念介绍 SSM项目是指基于SpringSpringMVCMyBatis框架搭建的Java Web项目。 Spring是负责管理和组织项目的IOC容器和…

二、C#—第一个c#程序(2)

&#x1f33b;&#x1f33b; 目录 一、编写第一个C#程序1.1 使用Visual Studio创建c#程序的步骤1.2 编写第一个程序“Hello Word”1.3 c#程序的基本结构1.3.1 c#中的命名空间1.3.2 c#中的类1.3.3 c#中的程序启动器——Main方法1.3.4 c#中的标识符1.3.5 c#中的关键字1.3.6 c#中的…

Vavido IP核Independent Clocks Block RAM FIFO简述

文章目录 1 FIFO&#xff08;先入先出&#xff09;1.1 概念1.2 应用场景1.3 FIFO信号1.4 FIFO读写时序1.4.1 FIFO读时序1.4.2 FIFO写时序 参考 1 FIFO&#xff08;先入先出&#xff09; 1.1 概念 FIFO&#xff08;First in First out&#xff09;即先入先出队列&#xff0c;是…

个性化定制界面还是极简版原装界面?我的选择是……

个性化定制界面和极简版原装界面&#xff0c;哪一个你用起来更加顺手呢&#xff0c;相比之下你更喜欢哪一个&#xff1f;来聊一聊原因吧&#xff01; 一、我的观点和选择 个性化定制界面和极简版原装界面&#xff0c;二者各有优缺点。 &#xff08;一&#xff09;极简版原装…

windows vmware17虚拟机导出、导入

我采用的是vmware17版本的虚拟机软件 直接拷贝VM虚拟机文件 导出 查看虚拟机所在路径 复制整个文件夹&#xff0c;可以先压缩介绍文件大小&#xff0c;拷贝到需要还原该虚拟机的电脑上 导入 在目的电脑上需要安装vnware17版本的虚拟机软件 直接打开vmware17&#xff0c; 选…

Mysql--对varchar字段用int数值来查询的问题

在工作中遇到的一个问题。就是mysql的一个表中的一个字段是varchar类型的&#xff0c;这个字段用来存储身份证&#xff0c;身份证正好是18位的。但是在根据身份证号来查询用户的时候&#xff0c;忘了给这个查询条件的身份证号加上’""&#xff0c;然后就产生了问题。…

Pinia能否替代 Vuex 的更强大状态管理工具

前序 Pinia 是 Vue.js 团队成员专门为 Vue 开发的一个全新的状态管理库&#xff0c;也相当于vuex5&#xff0c;下面关于vuex5的提案是不是觉得很像 Vuex5 的提案 Pinia和Vuex的函数 Vuex&#xff1a; State、Getters、Mutations(同步)、Actions(异步) Pinia&#xff1a; St…

【C++进阶】模板进阶

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

SpringBoot项目集成Druid

文章目录 一、前言二、Druid相关内容1、Druid简介1.1数据库连接池 2、项目集成Druid2.1、环境准备2.2、依赖准备2.3、编写配置文件2.4、测试访问 3、功能介绍3.1、查看数据源3.2、SQL监控3.3、URI监控 三、总结提升 一、前言 本文将介绍Druid的相关内容以及项目如何集成Druid&…

每日一题(复制带随机指针的链表)

每日一题&#xff08;复制带随机指针的链表&#xff09; 138. 复制带随机指针的链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 由于每个链表还包含了一个random节点指向了链表中的随机节点&#xff0c;所以并不能直接照搬复制原链表。首先想到的暴力思路是复…

Self-Attention Transformer完全指南:像Transformer的创作者一样思考

本文从RNN到self-attention&#xff0c;再到Transformer来讲清楚整个算法。 近半年来有大量同学来找我问Transformer的一些细节问题&#xff0c;例如Transformer与传统seq2seq RNN的区别、self-attention层的深入理解、masked self-attention的运作机制&#xff1b;以及各种Tr…