咳咳,先说说我的问题:
表中存储的数据是包含html标签的,导致模糊搜索时可能会匹配到html标签
比如,要查询的字符是:p,表中的内容是:
虽然p在html标签中,并不属于真正要展示的内容,但是还是匹配上了
先给出最后的解决方案(p表示查询的字符串):
select content from table where content regexp '>[^<]*p[^>]*<';
解释:就是用正则表达式匹配查询字符串不在<>中的部分
思路:
看了很多博客,一开始看的是用存储过程解决,但是拿到的存储过程代码并不能执行,奈何我已经完全不会存储过程了,遂放弃
然后,看别人说用regexp_replace可以解决,试了半天,发现mysql8的版本才开始支持,我的版本是5.7,再次放弃
再然后,就看到了regexp的解决方案,发现真的可以
参考:https://segmentfault.com/q/1010000014372808?utm_source=sf-similar-question
最后,用在代码上又出问题了,我的架构是使用mybatis plus的LambdaQueryWrapper来查询的,而且目前的代码没有自己手写sql,但是LambdaQueryWrapper目前提供的方法中没有支持正则表达式的,经过我一番探寻,找到了apply方法, 可以添加正则表达式,嘿嘿!
apply具体用法见 : 条件构造器 | MyBatis-Plus
到这,这个问题差不多就结束了,但是还有一个坑,就是如果内容是
<span>JA</span>VA
我想查JAVA是查询不到的,目前还没有解决这个问题!
再附加一个问题,就是需要后端对查询到的字段进行高亮显示,具体做法就是:
<span style="color: blue;"> 查询的字符串 </span>
但是,如果查询的字符串既包含在html标签中了,又包含在内容中,就有可能会出现这样的情况
<p>ap</p>
===>>>>>
<<span style="color: blue;">p</span>>a<span style="color: blue;">p</span>></<span style="color: blue;">p</span>>
所以,加span标签的时候,也要过滤掉html标签, 如下
/**
* 高亮显示搜索值
*
* @param queryValue 搜索值
* @param targetValue 原值
* @return 高亮显示的搜索值
*/
public static String dealQueryParamHighLight(String queryValue, String targetValue) {
String resultValue = "";
String regex = "<[^>]*" + queryValue + "[^>]*>";
Pattern r = Pattern.compile(regex);
if (StringUtil.isNotEmpty(queryValue)) {
int index;
// 是否包含搜索值
while (targetValue.contains(queryValue)) {
Matcher m = r.matcher(targetValue);
if (!m.find()) {
index = targetValue.indexOf(queryValue);
resultValue += targetValue.substring(0, index) + "<span style=\"color: blue;\">" + queryValue + "</span>";
targetValue = targetValue.substring(index + queryValue.length());
}
// 匹配的字符在<>中, 直接过滤掉<>中所有字符,不匹配
else {
index = m.end();
resultValue += targetValue.substring(0, index);
targetValue = targetValue.substring(index);
}
}
if (StringUtil.isNotEmpty(targetValue)) {
resultValue += targetValue;
}
} else {
resultValue = targetValue;
}
return resultValue;
}
还有一个坑要注意的就是,正则匹配的时候,要用find,我一直用matches,就导致我的正则表达式一直都不生效,可能是我的用法问题