一、需求二、设计
1、背景2、思路 三、Java代码实现四、DSL表达式五、前端拼接 DSL 字符串六、Java使用ES查询DSL字符串七、通过 Apifox 测试八、前端展示效果 一、需求
1、实现一个搜索框,可以实现所有的字段的查询,并且每个字段可以支持不同的查询方式
如下图所示
2、点击任何一个字段,弹出该字段支持的查询方式
由于项目是前后端分离项目,这里就需要前端的配合
由于我们的数据库选择是 mysql+es
今天这篇文章主要是使用es进行业务查询
如何获取该表的所有列字段?如果根据字段类型给与对应的查询条件?
这里我是使用 Java开发的,所以第一点直接想到的就是使用反射
实现思路
首先需要将所有列表,创建对应的实体类(即:每一列对应实体每个字段)然后前端传入具体为哪一个类的类型,通过反射获取其所有字段名然后我们这里会根据字段的数据类型,决定使用的判断方式(即:string:使用 “=”, “!=”, “:”, “!:” )最后组装数据返回前端前端使用 DSL 表达式 ,拼接 DSL字符串回传java进行查询Java根据DSL表达式查询 并返回结果 三、Java代码实现
这里定义了2种判断条件
STRING = {"=", “!=”, “:”, “!:”};OTHER = {"=", “>”, “<”, “!=”};
@Slf4j@Service("AwsScanService")public class AwsScanServiceImpl implements AwsScanService { // string 类型下 private static final String[] STRING = {"=", "!=", ":", "!:"}; // 非 string 类型下 private static final String[] OTHER = {"=", ">", "<", "!="}; @Override public R getScanSearchFields(ScanBasicVo index) { Class cls = getObject(index.getServiceId()); log.info("获取当前对象的类型为:" + cls); Field[] fields = cls.getDeclaredFields(); Map
具体的对应的每个vo就不在这里一一展示了
下面来看一下最后的执行返回结果
{ "msg": "success", "code": 20000, "data": { "dyTableName": [ "=", ">", "<", "!=" ], "tableStatus": [ "=", ">", "<", "!=" ], "tableSizeBytes": [ "=", ">", "<", "!=" ], "itemCount": [ "=", ">", "<", "!=" ] }}
四、DSL表达式# 等于GET /aws_1_1_ec2/_search{ "query": { "match": { "instanceName": "unipus-ucont-apiworker102" } }}# 不等于GET /aws_1_1_ec2/_search{ "query": { "bool": { "must_not": { "term": { "instanceName": "unipus-ucont-apiworker102" } } } }}# 模糊查询GET /aws_1_1_ec2/_search{ "query": { "wildcard": { "instanceName":{"value":"*ucont*"} } }}# 不包含GET aws_1_1_ec2/_search{ "query":{ "bool" : { "must_not" : { "wildcard" : { "type" : "*c4*" } } } } }# 范围内查询GET /aws_1_1_ec2/_search{ "query": { "bool": { "must": { "range": { "cpuMax": { "gte": 15, "lte": 18 } } } } }}# 多关系查询GET aws_1_1_ec2/_search{ "query": { "bool": { "should": [ { "wildcard": { "type": "*c5*" } }, { "bool": { "must_not": [ { "wildcard": { "vpcName": { "value": "*Test*" } } } ] } } ] } }}
五、前端拼接 DSL 字符串 这里需要注意,java接收的dsl字符串不能包含最外层的 「query」关键字
比如上面的DSL查询转化为字符串
"{ “match”:{ “platform”:“windows” } } "
这里目前还没有给前端找到更好的插件,也欢迎在前端拼接过DSL的朋友留言!!!
六、Java使用ES查询DSL字符串查询dsl字符串查询es的方法
@PostMapping("/dsl/query") public PageUtils queryDslToEs(@RequestBody ScanCommonVo scanCommonVo) throws IOException { String dsl = scanCommonVo.getDsl(); String index = scanCommonVo.getIndex(); //分页 long curPage = scanCommonVo.getPage() == 0 ? 1 : scanCommonVo.getPage(); long limit = scanCommonVo.getLimit() == 0 ? 10 : scanCommonVo.getLimit(); // 返回结果 List
传入的vo
@Datapublic class ScanCommonVo extends BasicVo { @NotBlank(message = "dsl 表达式不能为空") private String dsl; @NotBlank(message = "索引") private String index;}@Data@ApiModel(description = " aws 基类")public class BasicVo { @ApiModelProperty(value = "当前页索引") private Long page; @ApiModelProperty(value = "每页大小") private Long limit;}
七、通过 Apifox 测试 关键词查询与分页查询都ok