首页 > 数据库 >设计思路-mysql进行分词搜索

设计思路-mysql进行分词搜索

时间:2023-02-16 10:55:06浏览次数:32  
标签:word String final StringUtil return 搜索 mysql input 分词

有时候我们数据量很少,但是需要全文检索,如果用es的话就太重了。要引入新的技术栈,当然mysql高版本支持全文检索

但是我们再低版本情况下怎么做

 

工具类

@Slf4j
public class HanLPUtil {
    // 分词需要跳过的片段:标点,语气,助词,动词等
    // https://github.com/hankcs/HanLP/blob/1.x/data/dictionary/other/TagPKU98.csv
    private final static String[] SKIP_SEGMENT_NATURE = {"w", "y", "u", "v"};
    private final static String[] SPECIA_KEYWORDS = {"'", "%", "_", "\\", "$", "^", "*", "(", "+", "?", "["};
    private final static String[] REPLACE_KEYWORDS = {"\\\'", "\\%", "\\_", "\\\\\\\\", "\\$", "\\^", "\\*", "\\(", "\\+", "\\?", "\\["};

    public static String segment(String input, String split) {
        return HanLPUtil.segment(input, split, 0);
    }

    public static String segment(String input, String split, int mode) {
        if (StringUtil.isEmptyOrNullString(input)) {
            return input; // null skipped.
        }
        input = StringUtil.trim(input.replace(split,""));
        final List<Term> termList = IndexTokenizer.segment(input);

        // 跳过标点,语气词,助词,动词等
        final List<Term> filteredTermList = termList.stream()//
                .filter(e -> !needSkip(e)).collect(Collectors.toList());

        final List<String> filteredWords = new ArrayList<>();
        // 全文也加入分词结果
        filteredWords.add(input);

        // 两两拼接(跳过单个字符)
        if (mode == 0) {
            for (int i = 0; i < filteredTermList.size(); i++) {
                final Term current = filteredTermList.get(i);
                final Term prev = (i - 1 >= 0) ? filteredTermList.get(i - 1) : null;
                if (null == prev) {
                    continue;
                }
                String word = StringUtil.trim(prev.word + current.word);
                if (StringUtil.isBlank(word) || StringUtil.equals(split, word) || word.length() < 1) {
                    continue;
                }
                filteredWords.add(word);
            }
        }
        // 直接过滤后分词结果(跳过单个字符)
        else if (mode == 1) {
            for (Term term : filteredTermList) {
                String word = StringUtil.trim(term.word);
                if (StringUtil.isBlank(word) || StringUtil.equals(split, word) || word.length() < 1) {
                    continue;
                }
                filteredWords.add(word);
            }
        }

        if (log.isDebugEnabled()) {
            log.info("#1103 HanLPUtil.segment() input={}, mode={}, result={}", input, mode, filteredWords);
        }

        // 最终结果以分隔符拼接
        return StringUtil.join(filteredWords, split);
    }

    private static boolean needSkip(Term term) {
        if (null == term || null == term.word) return true;

        for (String nature : SKIP_SEGMENT_NATURE) {
            if (term.nature.startsWith(nature))
                return true;
        }
        return false;
    }

    /**
     * SQL的LIKE/REGEXP查询语句中,有一些特殊的字符,需要转换后才能搜索到结果:
     * ':用于包裹搜索条件,需转为\';
     * %:用于代替任意数目的任意字符,需转换为\%;
     * _:用于代替一个任意字符,需转换为\_;
     * \:转义符号,需转换为\\\\。
     * ....
     */
    public static String filterSpecia(String keyword) {
        if (StringUtil.isEmptyOrNullString(keyword)) return keyword;
        final StringBuilder result = new StringBuilder();
        for (char keywordChar : keyword.toCharArray()) {
            boolean isReplace = false;
            for (int i = 0; i < SPECIA_KEYWORDS.length; i++) {
                if ((keywordChar + "").equals(SPECIA_KEYWORDS[i])) {
                    result.append(REPLACE_KEYWORDS[i]);
                    isReplace = true;
                    break;
                }
            }
            if (!isReplace) {
                result.append(keywordChar);
            }
        }
        return result.toString();
    }
}

1.先转义

// 特殊字符转义
searchKey = HanLPUtil.filterSpecia(searchKey)

2分词条件

 HanLPUtil.segment(filterSpeciaWithSearchKey, "|", 1)

3.搜索条件

 a.body REGEXP '还有一些特殊字符|一些|特殊|字符' OR body like '%有一些特殊字符一些特殊字符'





标签:word,String,final,StringUtil,return,搜索,mysql,input,分词
From: https://www.cnblogs.com/LQBlog/p/17125936.html

相关文章

  • MySQL 数据库(表字段)命名规范
    一、数据库命名规范采用26个英文字母(区分大小写)和0-9的自然数(一般经常不需要加)加上下划线_组成,命名简洁明确,多个单词用下划线_分隔,一个项目一个数据库,多个项目慎用同一......
  • mysql事务隔离
    前言简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在MySQL中,事务支持是在引擎层实现的。你现在知道,MySQL是一个支持多引擎的系统,但并不是所有的引擎都......
  • mysql事务隔离级别及实现原理,深度理解
    1、事务是什么?事务是数据库一个不可分的工作单元,可以将多个操作步骤表示为一个步骤。2、事务的四大特性Atomicity原子性,Consistency一致性,Isolation隔离性,Durability持......
  • 解决mysqlclient安装报缺少Microsoft Visual C++ 14.0 is required
    安装mysqlclient报错error:MicrosoftVisualC++14.0isrequired.Getitwith“MicrosoftVisualC++BuildTools”1.不要去下载VisualStudio!!!==没什么用(对我而言)......
  • 2.mysql存储过程、存储函数与触发器
    --创建一个存储过程DELIMITER$CREATEPROCEDURE存储过程名称(返回类型参数名1参数类型1,....)[......]BEGIN--具体组成存储过程的SQL语句....END$DE......
  • 1.mysql创建索引
    --创建一个普通索引(方式①)createindex索引名ON表名(列名(索引键长度)[ASC|DESC]);--创建一个普通索引(方式②)altertable表名addindex索引名(列名(索引键长度)......
  • mysql keepalive +双主架构注意问题
    具体搭建参考Linux两节点+keepalive搭建MySQL双主集群-So怪咖-博客园(cnblogs.com)auto_increment_offset=1#双主复制中,2台服务器的自增长字段初值分别配置为1......
  • 【WPF】带模糊搜索的DataGrid
    带模糊搜索的DataGrid前端代码view<Windowx:Class="MVVM.Views.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:......
  • 深度优先搜索算法-dfs讲解
    迷宫问题有一个迷宫:S**.....***T(其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需要从S出发走到T,每次只能向上下左右相邻的位置移动,不能走出地图,也......
  • mysql 实现insert update 功能
    <insertid="insertOrUpdateSelective"keyColumn="id"keyProperty="id"parameterType="com.xxx.xxx.UserDO"useGeneratedKeys="true">INSERTINTOuser<tr......