引言
公司公共平台数据全部接入了ES中,但是公司曾经有数据权限,是通过sql语句做的过滤,数据进入了ES中也需要按照同样的方式做数据过滤,这里我贴一下工具类
数据SQL转换工具类
package org.jeecg.common.es;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
import co.elastic.clients.json.JsonData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* ES权限控制工具类
* Author: WangLiang
* Date: 2023/10/7 11:12
*/
public class ESDataPermissionUtil {
/**
* 根据提供的条件map和构造的query拼接过滤条件
*
* @param dataRoleMap
* @param boolQuery
*/
public static void addFilterRule(Map<String, List<SysPermissionDataRuleModel>> dataRoleMap, BoolQuery.Builder boolQuery) {
// 过滤数据权限
// 对拿到的数据进行分组,每一组之间用 and 分割,组内用 or 分割;
// 例: where (condition1 = x or condition2 < x or condition3 < x) and (condition4 = x or condition5 = x)
for (Map.Entry<String, List<SysPermissionDataRuleModel>> entry : dataRoleMap.entrySet()) {
BoolQuery.Builder boolGroupQuery = new BoolQuery.Builder();
List<SysPermissionDataRuleModel> dataList = entry.getValue();
List<Query> queryList = new ArrayList<>();
for (SysPermissionDataRuleModel model : dataList) {
queryList.add(ruleConvertFilter(model));
}
boolGroupQuery.should(queryList);
boolQuery.filter(f->f.bool(boolGroupQuery.build()));
}
}
/**
* 根据系统存入的数据过滤规则转换为ES的过滤规则
* @param model 系统model
* @return ES的query对象
*/
private static Query ruleConvertFilter(SysPermissionDataRuleModel model) {
String condition = model.getRuleConditions();
Query.Builder query = new Query.Builder();
if (condition.equals("=")) {
query.term(t -> t.field(model.getRuleColumn()).value(model.getRuleColumnvalue()));
} else if (condition.equals(">")) {
query.range(r -> r.field(model.getRuleColumn()).gt(JsonData.of(model.getRuleColumnvalue())));
} else if (condition.equals(">=")) {
query.range(r -> r.field(model.getRuleColumn()).gte(JsonData.of(model.getRuleColumnvalue())));
} else if (condition.equals("!=")) {
query.bool(q -> q.mustNot(m -> m.term(t -> t.field(model.getRuleColumn()).value(model.getRuleColumnvalue()))));
} else if (condition.equals("IN")) {
List<FieldValue> fields = new ArrayList<>();
String[] values = model.getRuleColumnvalue().split(",");
for (String value : values) {
fields.add(FieldValue.of(value));
}
query.terms(t -> t.field(model.getRuleColumnvalue()).terms(ms -> ms.value(fields)));
} else if (condition.equals("LIKE")) {
query.wildcard(m -> m.field(model.getRuleColumn()).value("*" + model.getRuleColumnvalue() + "*"));
} else if (condition.equals("LEFT_LIKE")) {
query.wildcard(m -> m.field(model.getRuleColumn()).value("*" + model.getRuleColumnvalue()));
} else if (condition.equals("RIGHT_LIKE")) {
query.wildcard(m -> m.field(model.getRuleColumn()).value(model.getRuleColumnvalue() + "*"));
} else if (condition.equals("<")) {
query.range(r -> r.field(model.getRuleColumn()).lt(JsonData.of(model.getRuleColumnvalue())));
} else if (condition.equals("<=")) {
query.range(r -> r.field(model.getRuleColumn()).lte(JsonData.of(model.getRuleColumnvalue())));
}
return query.build();
}
}
搜索方法:
public <T> HitsMetadata<T> fulltextsearch(List<OnlCgformComb> searchConfigList, String keyword, Integer page, Integer limit, boolean isHighLight,Class<T> beanClass) throws Exception {
if (searchConfigList==null || searchConfigList.size()==0) {
//test code
searchConfigList = new ArrayList<>();
OnlCgformComb obj1 = new OnlCgformComb();
obj1.setTableName("his_sys_user");
obj1.getFields().add("realname");
obj1.getFields().add("username");
searchConfigList.add(obj1);
OnlCgformComb obj2 = new OnlCgformComb();
obj2.setTableName("his_bus_project_summary");
obj2.getFields().add("fd_name");
obj2.getFields().add("fd_project_name");
searchConfigList.add(obj2);
OnlCgformComb obj3 = new OnlCgformComb();
obj3.setTableName("his_bus_createtable");
obj3.getFields().add("fd_name");
obj3.getFields().add("fd_file");
searchConfigList.add(obj3);
}
String[] keywordarry=keyword.split(" ");
SearchRequest.Builder builder = new SearchRequest.Builder();
//设置查询索引
List<String> indexNameList=new ArrayList<String>();
BoolQuery.Builder boolMustQuery = new BoolQuery.Builder();
for (OnlCgformComb searchConfig : searchConfigList )
{
indexNameList.add(searchConfig.getTableName());
List<String> fdnamelist = searchConfig.getFields();//
BoolQuery.Builder boolQuery = new BoolQuery.Builder();
boolQuery.must(
q -> q.term(m -> m.field("_index").value(searchConfig.getTableName()))
);
// 过滤权限条件
if( !ObjectUtils.isEmpty(searchConfig.getDataRole()) ){
Map<String, List<SysPermissionDataRuleModel>> dataRoleMap = searchConfig.getDataRole();
ESDataPermissionUtil.addFilterRule(dataRoleMap,boolQuery);
}
for (String singlekeyword :keywordarry) {
if (StringUtils.hasText(singlekeyword.trim())) {
boolQuery.must(
q -> q.multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder
.fields(fdnamelist).query(singlekeyword.trim()).operator(Operator.Or).analyzer("ik_smart"))
);
}
}
//builder.query(q -> q.multiMatch(multiMatchQueryBuilder -> multiMatch))
boolMustQuery.should(q -> q.bool(boolQuery.build()));
}
builder.query(q -> q.bool(boolMustQuery.build()));
/* String jsonhighlight="{" +
" \"pre_tags\": [\"<a>\"]," +
" \"post_tags\": [\"</a>\"]," +
" \"fields\": {\"*\": {}}" +
" }";
ObjectMapper om = new ObjectMapper();
var node = om.readTree(jsonhighlight);
Highlight highlight =Highlight.of(x->x.withJson());
builder.highlight(highlight);*/
if (isHighLight) {
builder.highlight(h -> h.preTags("<font color='red'>").postTags("</font>").fields("*", x -> x));
}
builder.allowNoIndices(true).ignoreThrottled(true).ignoreUnavailable(true);
//分页
if(page!=null && limit!=null){
builder.from(page*limit).size(limit);
}
SearchResponse<T> response=null;
ElasticsearchClient client = null;
try {
client = ESClientPool.getClient();
response = client.search(builder.build(), beanClass);
return response.hits();
}
catch (Exception e) {
// log.error("Exception fulltextsearch"+e.getMessage(), e);
throw e;
}
finally {
if (client!=null)
{
ESClientPool.returnClient(client);
}
}
// return null;
}