多个关键字用or、and、包含、不包含动态拼接为正则表达式和SQL查询条件

news2024/11/24 16:55:14

目录

  • 前言
    • 校验
  • 思路
    • 1、存储方式
    • 2、实现
      • 图一实现
      • 图二实现
      • 结果
  • 最后

前言

不知道大家有没有做过这种需求:在某字符串中,根据多个关键字去判断这串字符串是否满足条件。如下图:
图1
亦或是
图2
在这里插入图片描述

如果说要根据图二的关键字去数据库中查询符合条件的数据,要怎么做?是不是感觉头都大了?
暂且先不说包含、不包含,我们先来说说或、且。多个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',字段名)>0

where条件拼出来了,那如果我觉得用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关键字7

在这里插入图片描述

2、实现

图一实现

我们先用 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.length>1){
            result.append("(");
            for (int j = 0; j < andSplit.length; j++) {
                result.append("(.*?"+andSplit[j]+".*?)");
            }
            result.append(")");
        }else {
            result.append("(.*?"+orSplit[i]+".*?)");
        }
        if (i<orSplit.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.length>1){
            result.append("(");
            for (int j = 0; j < andSplit.length; j++) {
                result.append("locate('"+andSplit[j]+"',"+field+")>0");
                if (j<andSplit.length-1){
                    result.append(" and ");
                }
            }
            result.append(")");
        }else {
            result.append("locate('"+orSplit[i]+"',"+field+")>0");
        }
        if (i<orSplit.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.length>1){
            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 (c1==0) sb1.append("((?!");
                    if (c1>0) sb1.append("|");
                    sb1.append(andSplit[j].replace("no",""));
                    c1++;
                }
                if (j==andSplit.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 (c2==0) 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 (i<orSplict.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.length>1){
            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 (j<andSplit.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 (i<orSplit.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、or
    String 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关键字8
    String 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));
}

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

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

相关文章

QT基础(18)- QAbstractSocket

QT基础&#xff08;18&#xff09;- QAbstractSocket1 创建简单的客户端2 QAbstractSocket2.1 简介2.2 枚举2.2.1 BingFlag2.2.2 NetworkLayerProtocol2.2.3 PauseMode2.2.4 SocketError2.2.5 SocketOption2.2.6 SocketType2.2.7 SocketState2.3 公有函数2.3.1 构造函数2.3.2 a…

文献阅读(47)—— 遗传数据研究近视和眼压与视网膜脱落的关系

文献阅读&#xff08;47&#xff09;—— 遗传数据研究近视和眼压与视网膜脱落的关系 文章目录文献阅读&#xff08;47&#xff09;—— 遗传数据研究近视和眼压与视网膜脱落的关系遗传数据研究近视和眼压与视网膜脱落的关系先验知识/知识拓展文章结构文章结果1. 视网膜脱落风险…

centos8安装docker运行java文件

本文由个人总结&#xff0c;如需转载使用请标明原著及原文地址 这里是基于我前一篇搭的centos8服务器做的&#xff0c;如果yum baseos源或appstream源有问题可以去看看前一篇 https://blog.csdn.net/qq_36911145/article/details/129263830 1.安装docker 1.1配置docker yum…

惠普战66pro如何选购内存条?一篇文章讲解清楚

笔记本&#xff1a;惠普 ZHAN66 PRO CPU&#xff1a;Intel Core™ i-8565U CPU 1.80GHz 内存条&#xff1a;Samsung PS: 如果有需要更换硬盘的可以看我之前发的文章&#xff0c;博主进行了长时间的测试。 硬盘选购长测评 文章目录前言一、内存是什么&#xff1f;二、如何操作呢…

错误:EfficientDet网络出现“No boxes to NMS“并且mAP:0.0的解决方案

近日&#xff0c;在使用谷歌新推出来的一个网络EfficientDet进行目标检测训练自己的数据集的时候&#xff0c;出现了如下错误&#xff1a; 其中项目开源地址是&#xff1a;https://github.com/toandaominh1997/EfficientDet.Pytorch 上面截图中的1和2代表我的类别名称。读者可…

【计算机二级python】综合题题目

计算机二级python真题 文章目录计算机二级python真题一、八十天环游世界二、八十天环游世界 问题一二、八十天环游世界 问题二一、八十天环游世界 附件中保存1个文本文件&#xff0c;分别对应2个问题‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬…

315线上知识竞赛答题活动方案及模板分享

315线上知识竞赛答题活动方案及模板分享在315国际消费者权益日来临之际&#xff0c; 很多单位推出有奖知识竞答&#xff0c; 希望大家在了解专业知识的同时&#xff0c; 还可以拿到自己喜欢的奖品&#xff01;这是消费者委员会和监管局联合举办的“315消费知识在线有奖竞答”活…

Springboot怎么集成Thymeleaf模板引擎?

Thymeleaf介绍Thymeleaf&#xff0c;是一个XML/XHTML/HTML模板引擎&#xff0c;开源的java库&#xff0c;可以用于SpingMVC项目中&#xff0c;用于代替JSP、FreeMarker或者其他的模板引擎&#xff1b;页面与数据分离&#xff0c;提高了开发效率&#xff0c;让代码重用更容易。S…

【JavaScript速成之路】JavaScript流程控制

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;流程控制2&#xff0c;分支结构2.1&#xff0c;if语句2.2&…

时机将至,名创优品或将再掀起一波消费热浪

北京时间2月28日&#xff0c;名创优品发布2023财年中报&#xff0c;财报显示&#xff0c;2023财年第二季度营收规模有所收窄&#xff0c;但净利润、毛利率、门店数量均实现了不错的增长&#xff0c;总体表现可圈可点。 &#xff08;资料来源&#xff1a;富途牛牛&#xff09; …

PIC单片机的快速代码生成和调试过程

1.相关工具说明&#xff1a;MCC ...................................Pic的代码模板软原始安装包&#xff1a;mcc-installer-5.2.2-windows.exeMPLAB X IDE ........................... 集成开发环境原始安装包&#xff1a;MPLABX-v6.00-windows-installer.exe编译环境&#x…

自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测

自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测 目前目标检测算法有很多&#xff0c;流行的就有faster-rnn和yolov&#xff0c;本文使用了几年前的yolov3框架进行训练&#xff0c;效果还是很好&#xff0c;当然也可以使用更高版本的Yolov进行实战。本代码使…

八股总结(一)C++语法、内存管理、新标准、STL

layout: post title: 八股总结&#xff08;一&#xff09;C语法、内存管理、新标准、STL description: 八股总结&#xff08;一&#xff09;C语法、内存管理、新标准、STL tag: C 文章目录基础语法语言特性面向对象的三大特性&#xff1f;C中新增了string&#xff0c;它与C语言…

Acwing---843. n-皇后问题

n-皇后问题1.题目2.基本思想3.代码实现1.题目 n−皇后问题是指将 n 个皇后放在 nn 的国际象棋棋盘上&#xff0c;使得皇后不能相互攻击到&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 n&#xff0c;请你输出所有的满足条件的棋子摆法。 …

数据库调优策略

1.数据库调优的措施 1.1.调优的目标 尽可能节省系统资源&#xff0c;以便系统可以提供更大负荷的服务。(吞吐量更大)合理的结构设计和参数调整&#xff0c;以提高用户操作 响应的速度。(响应速度更快)减少系统的瓶颈&#xff0c;提高MySQL数据库整体的性能 1.2.如何定位调优…

Qt 绘制图表 - Qt Charts版

一、前言 自从 Qt 发布以来&#xff0c;给广大跨平台界面研发人员带来了无数的福利。但是Qt自己却一直没有提供自带的图表库&#xff0c;这就使得 QWT、QCustomPlot 等第三方图表库有了巨大的生存空间&#xff0c;为了降低开发成本&#xff0c;大家都涌向了这些第三方库。这种…

appium的安装详解

安装appium 爬虫手机APP需要实现自动化&#xff0c;所以要使用appnium来实现点击&#xff0c;输入&#xff0c;滑动等操作。由于appnium的安装较为繁琐&#xff0c;所以特意整理一篇文章来展示安装的详细过程过程中。 安装appnium共有3个步骤 安装 Android SDK安装 JDK安装 …

W800系列|ST-LINK|STM32最小版|HEX文件|CKLINK|DebugServer|学习(3):自制cklink调试工具

硬件准备 1.stm32最小系统板&#xff1a;stm32c8t6 2.stlink下载器&#xff1a;stlink v2版本 软件安装&#xff1a; 1、STM32 ST-LINK Utility&#xff08;官网下载&#xff09; 2、csky IDE: 剑池CDK集成开发环境V2.18.2 https://occ.t-head.cn/community/download?id…

链接投票二维码制作制作投票链接视频选举投票制作

关于微信投票&#xff0c;我们现在用的最多的就是小程序投票&#xff0c;今天的网络投票&#xff0c;在这里会教大家如何用“活动星投票”小程序来进行投票。我们现在要以“信赖挚友”为主题进行一次投票活动&#xff0c;我们可以在在微信小程序搜索&#xff0c;“活动星投票”…

activiti整合springBoot其他操作

如果单纯使用activiti进行流程的自动控制&#xff0c;是可以实现的。但是通常我们都需要结合自定义的表&#xff0c;便于在流程执行中更加清晰的看到每一个流程实例节点的具体信息。关联自定义表与activiti表才能完成真正的业务 BusinessKey关联 // 定义businessKey Test pub…