赞
踩
1、实现一个搜索框,可以实现所有的字段的查询,并且每个字段可以支持不同的查询方式
如下图所示
2、点击任何一个字段,弹出该字段支持的查询方式
由于项目是前后端分离项目,这里就需要前端的配合
由于我们的数据库选择是 mysql+es
今天这篇文章主要是使用es进行业务查询
这里我是使用 Java开发的,所以第一点直接想到的就是使用反射
实现思路
这里定义了2种判断条件
@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<String, Object> res = new HashMap<>();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
f.setAccessible(true);
try {
//f.getName()得到对应字段的属性名,f.get(o)得到对应字段属性值,f.getGenericType()得到对应字段的类型
log.info("属性名:" + f.getName() + ";字段类型:" + f.getGenericType());
if ("class java.lang.String".equals(f.getGenericType())) {
res.put(f.getName(), STRING);
}
res.put(f.getName(), OTHER);
} catch (IllegalArgumentException e) {
e.printStackTrace();
log.info("ReflectUtil error:" + e.toString());
}
}
return R.ok().put("data", res);
}
private Class getObject(int serviceId) {
switch (serviceId) {
case 1:
return AwsDynamodbVo.class;
case 2:
return AwsEc2CompareVo.class;
case 3:
return AwsEc2Vo.class;
case 4:
return AwsElasticacheVo.class;
case 5:
return AwsIAMVo.class;
case 6:
return AwsOpensearchVo.class;
case 7:
return AwsRdsVo.class;
case 8:
return AwsRiVo.class;
case 9:
return AwsS3Vo.class;
case 10:
return AwsVpcVo.class;
}
return null;
}
}
具体的对应的每个vo就不在这里一一展示了
下面来看一下最后的执行返回结果
{
"msg": "success",
"code": 20000,
"data": {
"dyTableName": [
"=",
">",
"<",
"!="
],
"tableStatus": [
"=",
">",
"<",
"!="
],
"tableSizeBytes": [
"=",
">",
"<",
"!="
],
"itemCount": [
"=",
">",
"<",
"!="
]
}
}
# 等于
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*"
}
}
}
]
}
}
]
}
}
}
这里需要注意,java接收的dsl字符串不能包含最外层的 「query」关键字
比如上面的DSL查询转化为字符串
"{ “match”:{ “platform”:“windows” } } "
这里目前还没有给前端找到更好的插件,也欢迎在前端拼接过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<Object> arrayRes = new ArrayList<>();
// String dsl = "{ \"match\":{ \"platform\":\"windows\" } } ";
// 判断索引是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest(index);
try {
// 如果不存在则返回
if (!restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT)) {
return new PageUtils(arrayRes, 0, (int) limit, (int) curPage);
}
// 如果存在则继续查询 dsl
WrapperQueryBuilder queryBuilder = new WrapperQueryBuilder(dsl);
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 设置分页
searchSourceBuilder.query(queryBuilder).from((int)curPage).size((int)limit);
searchRequest.source(searchSourceBuilder).indices(index);
SearchResponse searchResp = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 计算返回的条数
CountRequest countRequest = new CountRequest(index);
countRequest.query(queryBuilder);
long count = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT).getCount();
SearchHit[] searchHitArr = searchResp.getHits().getHits();
for (SearchHit searchHit : searchHitArr) {
Map<String, Object> temp = searchHit.getSourceAsMap();
// es自动生成的主键,然后插入现有的结果集中
// temp.put("id", searchHit.getId());
arrayRes.add(temp);
}
return new PageUtils(arrayRes, (int) count, (int) limit, (int) curPage);
} catch (IOException e) {
e.printStackTrace();
throw new RRException(BizCodeEnum.SEARCH_OPENSEARCH_INDEX_ERROR.getMessage(), BizCodeEnum.SEARCH_OPENSEARCH_INDEX_ERROR.getCode());
}
}
传入的vo
@Data
public class ScanCommonVo extends BasicVo {
@NotBlank(message = "dsl 表达式不能为空")
private String dsl;
@NotBlank(message = "索引")
private String index;
}
@Data
@ApiModel(description = " aws 基类")
public class BasicVo {
/**
* page 当前页索引
*/
@ApiModelProperty(value = "当前页索引")
private Long page;
/**
* 每页大小
*/
@ApiModelProperty(value = "每页大小")
private Long limit;
}
关键词查询与分页查询都ok
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。