网站建设const是什么意思,wordpress tag文件,阿里云预安装wordpress,网站发展趋势目录前言校验思路1、存储方式2、实现图一实现图二实现结果最后前言
不知道大家有没有做过这种需求#xff1a;在某字符串中#xff0c;根据多个关键字去判断这串字符串是否满足条件。如下图#xff1a; 亦或是
如果说要根据图二的关键字去数据库中查询符合条件的数据在某字符串中根据多个关键字去判断这串字符串是否满足条件。如下图 亦或是
如果说要根据图二的关键字去数据库中查询符合条件的数据要怎么做是不是感觉头都大了 暂且先不说包含、不包含我们先来说说或、且。多个or、and是不能同时并列使用的我们需要用括号将连续的、相同的or或者and用括号括起来。
比如图一我们按顺序连起来就是关键字1 and 关键字2 or 关键字3 or 关键字4 and 关键字5 or 关键字6 但是我们肯定不能直接就这么用我们得捋一捋要把括号加在哪哪些是并列的可以放在一个括号里的哪些又是放在括号外面的。按照我的想法是把连续 and 的关键字放在括号里括号外面就是 or。 所以得出来的条件就是(关键字1 and 关键字2) or 关键字3 or (关键字4 and 关键字5) or 关键字6
那么问题又来了我们要怎么把这个条件转换成SQL的where条件mysql中包含指定字符串我们用 locate 函数locate(‘关键字1’,字段1)0 就表示字段1的值包含关键字1如果是 0 则表示不包含。
于是我们拼出来的where条件就是
# (关键字1 and 关键字2) or 关键字3 or (关键字4 and 关键字5) or 关键字6
( locate(关键字1,字段名)0 and locate(关键字2,字段名)0 ) or locate(关键字3,字段名)0 or
( locate(关键字4,字段名)0 and locate(关键字5,字段名)0 ) or locate(关键字6,字段名)0where条件拼出来了那如果我觉得用locate拼的条件太长了想用正则或者需要在java代码中用正则表达式匹配呢该怎么把这个条件转换成正则表达式
包含的话在正则中我们可以用 .* 但这个是贪婪匹配匹配任意次我们只需要匹配一次就够了所以可以用 .*? and 的话直接括号并列就行or 的话则用 | 表示。 于是得到得正则表达式就是
((.*?关键字1.*?)(.*?关键字2.*?))|(.*?关键字3.*?)|((.*?关键字4.*?)(.*?关键字5.*?))|(.*?关键字6.*?)校验
得到了两种查询方式的条件那我们来验证一下准备一张测试表
DROP TABLE IF EXISTS test1;
CREATE TABLE test1 (id bigint NOT NULL AUTO_INCREMENT,content varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 内容,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT Dynamic;INSERT INTO test1 VALUES (1, 这里是测试内容关键字1内容哈哈哈关键字2内容内容、关键字3、测试关键字4测试测试内容关键字5关键字6。);
INSERT INTO test1 VALUES (2, 生死关键字1并非我能关键字4左右善恶也非关键字4我能独断);
INSERT INTO test1 VALUES (3, 但我之关键字4本心将为我选择关键字5方向我之使命将为关键字6我决断对错纵使这世间混关键字1沌不堪我也希望用关键字3这一身赤关键字3羽开辟曙光。);
INSERT INTO test1 VALUES (4, 神州关键字4之地守护者关键字4沉眠已久。关键字1铭刻编年关键字7此刻乃是关键字4苏醒之时。奔赴关键字7远方重燃此世之炽。);
INSERT INTO test1 VALUES (5, 以精准完关键字5美的攻击关键字5击退关键字6一切混沌与关键字7无序!关键字8);
INSERT INTO test1 VALUES (6, 身披关键字7秩序之衣穷尽关键字7武道之关键字5极。);
INSERT INTO test1 VALUES (7, 漫漫关键字1白夜划过天际的关键字2星辰不计关键字1其数但旷关键字2古闪耀关键字3的明星仅此一人。);
INSERT INTO test1 VALUES (8, 就昆仑山搭街坊卡拉天热广泛的撒旦发射点。关键字5);
INSERT INTO test1 VALUES (9, 太艰苦拉关键字6萨大家发了肯定解开了简历库进口量。);
INSERT INTO test1 VALUES (10, 这个是测试内关键字3容呀测试测试测试内容内容内容这个是测试内容呀。);
INSERT INTO test1 VALUES (11, 空手道解放昆仑山搭关键字4街坊特我认为若i速关键字4冻i夫。解开了揭开角度来看请问热关键字4望热望热热退热贴烹饪例如可通过大幅高开。);
INSERT INTO test1 VALUES (12, 哈哈哈哈关键字5哈哈请问请问啦啦啦关键字5啦啦啦啦了哈哈哈哈哈哈钱关键字5钱钱钱钱钱钱嘎嘎嘎嘎嘎嘎嘎反反复复烦烦烦。);验证方式一
SELECT *
FROM test1
WHERE
( locate(关键字1,content)0 and locate(关键字2,content)0 ) or locate(关键字3,content)0 or
( locate(关键字4,content)0 and locate(关键字5,content)0 ) or locate(关键字6,content)0验证方式二
SELECT *
FROM test1
WHERE content REGEXP ((.*?关键字1.*?)(.*?关键字2.*?))|(.*?关键字3.*?)|((.*?关键字4.*?)(.*?关键字5.*?))|(.*?关键字6.*?)这么看两种条件方式查出来的结果都是一样的。 既然这么做的思路没问题那我们接下来要解决的就是怎么动态去拼接出这个where条件和正则表达式。
思路
1、存储方式
第一步我们先要考虑清楚图一图二添加了多个关键字后要以什么形式存储能更方便我们后续进行动态拼接。 我的想法是直接把这些关键字用or、and连起来后续用的时候也是用or、and进行分割像这样
# 图一or、and也可以用其他符号代替比如or用 | and用
关键字1and关键字2or关键字3or关键字4and关键字5or关键字6# 图二包含、不包含则分别用 is、no代替
is关键字1orno关键字2andno关键字3andis关键字4oris关键字5andis关键字6orno关键字72、实现
图一实现
我们先用 or 进行分割数组一每一个 or 后面都拼接上表示 “或” 的字符正则用 | 表示或SQL用 or 表示。
遍历数组一对每一个遍历的元素用 and 进行分割数组二如果数组二长度大于1说明有连续多个and这时我们要在这几个连续的and最外面加上括号把它们括起来表示这几个条件要同时满足。
即关键字1 and 关键字2 and 关键字3 —— ( (关键字1) and (关键字2) and (关键字3) )
用代码实现
/*** 根据关键字动态拼接正则表达式没有包含、不包含* param keyWord 关键字*/
public static String regByKeyWord1(String keyWord){String[] orSplit keyWord.split(or);StringBuffer result new StringBuffer();for (int i 0; i orSplit.length; i) {String[] andSplit orSplit[i].split(and);if (andSplit.length1){result.append(();for (int j 0; j andSplit.length; j) {result.append((.*?andSplit[j].*?));}result.append());}else {result.append((.*?orSplit[i].*?));}if (iorSplit.length-1){result.append(|);}}System.out.println(result.toString());return result.toString();
}/*** 根据关键字动态拼接SQL查询条件没有包含、不包含* param keyWord 关键字* param field 数据库条件字段*/
public static String whereByKeyWord1(String keyWord,String field){String[] orSplit keyWord.split(or);StringBuffer result new StringBuffer();for (int i 0; i orSplit.length; i) {String[] andSplit orSplit[i].split(and);if (andSplit.length1){result.append(();for (int j 0; j andSplit.length; j) {result.append(locate(andSplit[j],field)0);if (jandSplit.length-1){result.append( and );}}result.append());}else {result.append(locate(orSplit[i],field)0);}if (iorSplit.length-1){result.append( or );}}System.out.println(result.toString());return result.toString();
}得到的结果和上面自己推算的条件、正则是一样的。
图二实现
图二有包含、不包含就又要复杂一点了特别是正则表达式
因为本身对正则表达式也不熟用的时候都是直接在网上找。单个包含或不包含就没什么难度复杂的是多个包含不包含要一起使用着实花了我好大一番心思。 我先把代码贴出来
/*** 根据关键字动态拼接正则表达式有包含、不包含* param keyWord 关键字*/
public static String regByKeyWord2(String keyWord){String[] orSplict keyWord.split(or);StringBuffer result new StringBuffer();for (int i 0; i orSplict.length; i) {String[] andSplit orSplict[i].split(and);if (andSplit.length1){StringBuffer sb1 new StringBuffer();StringBuffer sb2 new StringBuffer();result.append(();int c1 0;for (int j 0; j andSplit.length; j) {if (andSplit[j].contains(no)){if (c10) sb1.append(((?!);if (c10) sb1.append(|);sb1.append(andSplit[j].replace(no,));c1;}if (jandSplit.length-1 sb1.length()0) sb1.append().)*);}int c2 0;for (int j 0; j andSplit.length; j) {if (!andSplit[j].contains(no)){if (sb1.length()0){if (c20) sb2.append(sb1.toString());sb2.append(andSplit[j].replace(is,)).append(sb1.toString());c2;}else {sb2.append((.*?andSplit[j].replace(is,).*?));}}}result.append(sb2.toString());result.append());}else {if (orSplict[i].contains(no)){result.append(((?!).append(orSplict[i].replace(no,)).append().)*);}else {result.append((.*?orSplict[i].replace(is,).*?));}}if (iorSplict.length-1){result.append(|);}}System.out.println(result.toString());return result.toString();
}/*** 根据关键字动态拼接SQL查询条件有包含、不包含* param keyWord 关键字* param field 数据库条件字段*/
public static String whereByKeyWord2(String keyWord,String field){String[] orSplit keyWord.split(or);StringBuffer result new StringBuffer();for (int i 0; i orSplit.length; i) {String[] andSplit orSplit[i].split(and);if (andSplit.length1){result.append(();for (int j 0; j andSplit.length; j) {if (andSplit[j].contains(no)){result.append(locate(andSplit[j].replace(no,),field)0);}else {result.append(locate(andSplit[j].replace(is,),field)0);}if (jandSplit.length-1){result.append( and );}}result.append());}else {if (orSplit[i].contains(no)){result.append(locate(orSplit[i].replace(no,),field)0);}else {result.append(locate(orSplit[i].replace(is,),field)0);}}if (iorSplit.length-1){result.append( or );}}System.out.println(result.toString());return result.toString();
}where条件拼接没什么好说的它和whereByKeyWord1一样。主要讲讲正则表达式该怎么写。
不包含用正则表示((?!关键字1).)*// 不包含 关键字1 和 关键字2
多个并列的不包含用正则表示((?!关键字1|关键字2).)*// 包含 关键字3但不包含 关键字1 和 关键字2
包含、不包含同时使用((?!关键字1|关键字2).)*关键字3((?!关键字1|关键字2).)*// 包含 关键字3 和 关键字4但不包含 关键字1 和 关键字2
多个包含、不包含同时使用(((?!关键字1|关键字2).)*关键字3((?!关键字1|关键字2).)*关键字4((?!关键字1|关键字2).)*)是不是感觉很复杂我也觉得很复杂。
包含不包含同时用时要先写不包含在不包含最后的星号后面接上包含的关键字。
只是我不明白为啥我前面明明有写不包含的表达式为啥包含后面还要再加上不包含的表达式 如果有多个包含、不包含同时使用那就会像第四条表达式一样开头要先写不包含然后接着第一个包含再写不包含后接着第二个包含然后又要写不包含。如此循环接下去。那这表达式不可谓不长。 不知道有没有更简单的表达式。
结果
// 图一
String keyWord 关键字1and关键字2or关键字3or关键字4and关键字5or关键字6;
String reg DynamicWhereUtil.regByKeyWord1(keyWord);
String where DynamicWhereUtil.whereByKeyWord1(keyWord,content);
// 图一输出换行是为了方便查看实际输出结果没有换行
((.*?关键字1.*?)(.*?关键字2.*?))|
(.*?关键字3.*?)|
((.*?关键字4.*?)(.*?关键字5.*?))|
(.*?关键字6.*?)(locate(关键字1,content)0 and locate(关键字2,content)0) or
locate(关键字3,content)0 or
(locate(关键字4,content)0 and locate(关键字5,content)0) or
locate(关键字6,content)0// 图二
String keyWord is关键字1orno关键字2andno关键字3andis关键字4andis关键字5oris关键字6andis关键字7orno关键字8;
String reg DynamicWhereUtil.regByKeyWord2(keyWord);
String where DynamicWhereUtil.whereByKeyWord2(keyWord,content);
// 图二输出换行是为了方便查看实际输出结果没有换行
(.*?关键字1.*?)|
(((?!关键字2|关键字3).)*关键字4((?!关键字2|关键字3).)*关键字5((?!关键字2|关键字3).)*)|
((.*?关键字6.*?)(.*?关键字7.*?))|
((?!关键字8).)*locate(关键字1,content)0 or
(locate(关键字2,content)0 and locate(关键字3,content)0 and locate(关键字4,content)0 and locate(关键字5,content)0) or
(locate(关键字6,content)0 and locate(关键字7,content)0) or
locate(关键字8,content)0最后
终于是实现了开头的那两个需求以下是校验正则的测试代码
public static void main(String[] args) {// 1、只有and、orString keyWord1 关键字1and关键字2or关键字3or关键字4and关键字5or关键字6;String reg1 DynamicWhereUtil.regByKeyWord1(keyWord1 );//String where1 DynamicWhereUtil.whereByKeyWord1(keyWord1 ,content);String content1 110kV湾上甲线1721开关、变低、变低、CT高压试验;System.out.println(content1.matches(reg1 ));// 2、有and、or和包含、不包含// is关键字1 or (no关键字2 and no关键字3 and is关键字4 and is关键字5) or (is关键字6 and is关键字7) or no关键字8String keyWord2 is关键字1orno关键字2andno关键字3andis关键字4andis关键字5oris关键字6andis关键字7orno关键字8;String reg2 DynamicWhereUtil.regByKeyWord2(keyWord2);//String where2 DynamicWhereUtil.whereByKeyWord2(keyWord2,content);String content2 这里是关键字4hhh、哈哈哈关键字5666、关键字5好好好、关键字4关键字5;System.out.println(content2.matches(reg2));
}