作者官方网站:http://www.wxl568.cn
ElasticSearch查询工具提供高效,方便易用的查询接口,满足用户灵活多变的查询功能
ElasticSearch是一款分布式的全文检索工具,支持对文本和结构化数据的查询。虽然ES很强大,但开发人员如果要去使用它需要
熟悉相关原理和查询语法,即使这样,要高效的使用它还需要积累相关的经验。
ElasticSearch查询工具可以在很大程度上提高开发人员效率,
提供高效的查询方式,同时提供灵活的查询条件组合模式。
1.ElasticSearch查询工具支持的检索操作符
and (&&)
or (||)
larger (>)
larger or equal to(>=)
less (<)
less or equal to(<=)
in
2.ElasticSearch查询的数据类型
long
double
date
string
3.同时支持查询条件组合
4.ES查询工具通过Scroll和回调函数的方式支持大数据量的检索
5.通过alibaba的fastjson提供高效的反序列化,屏蔽底层复杂数据结构,给开发人员更高层的抽象
/**
* 根据Id查询Es中的结果并转化为bean
* @param request
* @param targetClass
* @return bean
*/
public static <T> T getById(EsQueryRq request,Class<T> targetClass){
try{
Client client =getEsClient();
SearchRequestBuilder srb = client.prepareSearch(request.getIndex())
.setTypes(request.getType());
srb.setQuery(QueryBuilders.idsQuery().ids(request.getId()));
SearchResponse searchResponse = srb.execute().actionGet(DEFUALT_TIME_OUT_MILLS);
SearchHit[] hits = searchResponse.getHits().getHits();
return JSON.parseObject(hits[0].getSourceAsString(), targetClass);
}catch(Exception e){
logger.error("err in es getById",e);
}
return null;
}
/**
* 获取and map里面条件组成ES 识别的query
* @param request
* @return
*/
private static QueryBuilder getQueryByMatchAllMap(EsQueryRq request){
Map<String,String> fieldMap = request.getMatchAllFieldValueMap();
if (fieldMap!=null && !fieldMap.isEmpty()){
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
Iterator<String> it = fieldMap.keySet().iterator();
while(it.hasNext()){
String key = it.next();
bqb = bqb.must(QueryBuilders.termQuery(key, fieldMap.get(key)));
}
return bqb;
}
return null;
}
/**
* 根据多个属性值查询ES结果,多个属性之间是 and关系
* @param request
* @param targetClass
* @return list
*/
public static <T> List<T> getListByMatchAllMap(EsQueryRq request,Class<T> targetClass){
QueryBuilder queryBuilder = getQueryByMatchAllMap(request);
return getListByQuery(request,queryBuilder,targetClass);
}
/**
* 获取or map里面条件组成ES 识别的query
* @param request
* @return
*/
private static QueryBuilder getQueryByMatchOneMap(EsQueryRq request){
Map<String,String> fieldMap = request.getMatchOneFieldValueMap();
if (fieldMap!=null && !fieldMap.isEmpty()){
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
Iterator<String> it = fieldMap.keySet().iterator();
while(it.hasNext()){
String key = it.next();
bqb = bqb.should(QueryBuilders.termQuery(key, fieldMap.get(key)));
}
return bqb;
}
return null;
}
/**
* 根据多个属性值查询ES结果,多个属性之间是 or关系
* @param request
* @param targetClass
* @return list
*/
public static <T> List<T> getListByMatchOneMap(EsQueryRq request,Class<T> targetClass){
QueryBuilder queryBuilder = getQueryByMatchOneMap(request);
return getListByQuery(request,queryBuilder,targetClass);
}
/**
* 范围条件的查询,构造querBuilder对象
* @param request
* @return
*/
private static QueryBuilder getQueryByRangeList(EsQueryRq request){
List<RangeQuery> rangeList = request.getMatchAllRangeList();
if (rangeList != null) {
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
for (RangeQuery query : rangeList){
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(query.getQueryName());
setRangeValue(query,rangeQuery);
bqb = bqb.must(rangeQuery);
}
return bqb;
}
return null;
}
private static void setRangeValue(RangeQuery query,RangeQueryBuilder rangeQueryBuilder){
Method method;
try {
method = RangeQueryBuilder.class.getMethod(getMethodName(query), getParameter(query));
method.setAccessible(true);
method.invoke(rangeQueryBuilder, query.getValue());
} catch (NoSuchMethodException | SecurityException e) {
logger.error("err in EsQueryUtils reflect :",e);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
logger.error("err in EsQueryUtils reflect invocation :",e);
}
}
private static String getMethodName(RangeQuery queryBean){
switch (queryBean.getOperator()){
case LT:
return "lt";
case LTE:
return "lte";
case GT:
return "gt";
case GTE:
return "gte";
default:
return null;
}
}
private static Class<?> getParameter(RangeQuery queryBean){
switch (queryBean.getDataType()){
case DATE:
return Date.class;
case LONG:
return long.class;
case DOUBLE:
return double.class;
case STRING:
return String.class;
}
return String.class;
}
/**
* 根据范围条件查询列表
* @param request
* @param targetClass
* @return
*/
public static <T> List<T> getListByRange(EsQueryRq request,Class<T> targetClass){
QueryBuilder queryBuilder = getQueryByRangeList(request);
return getListByQuery(request,queryBuilder,targetClass);
}
/**
* 根据自定义的queryBuilder查询ES 对象
* @param request
* @param queryBuilder
* @param targetClass
* @return
*/
public static <T> List<T> getListByQuery(EsQueryRq request,QueryBuilder queryBuilder,Class<T> targetClass){
List<T> list = new ArrayList<>();
try{
if(queryBuilder !=null){
SearchRequestBuilder srb = getEsClient().prepareSearch(request.getIndex())
.setTypes(request.getType());
//使用constantScoreQuery 去掉score功能,提高查询性能
srb.setQuery(QueryBuilders.constantScoreQuery(queryBuilder));
SearchResponse searchResponse = srb.execute().actionGet(DEFUALT_TIME_OUT_MILLS);
SearchHit[] hits = searchResponse.getHits().getHits();
for(SearchHit hit:hits){
list.add(JSON.parseObject(hit.getSourceAsString(), targetClass));
}
}
}catch(Exception e){
logger.error("err in es getListByQuery:",e);
}
return list;
}
/**
* 使用scroll 查询大数据量结果集
* @param request
* @param queryBuilder
* @param callBack
*/
public static void doScanWithScroll(EsQueryRq request,QueryBuilder queryBuilder,ScrollReqCallBack callBack){
SearchResponse scrollResp = null;
try {
scrollResp = getEsClient().prepareSearch(request.getIndex()).setTypes(request.getType())
.setSearchType(SearchType.SCAN)
.setScroll(new TimeValue(SCROLL_KEEP_ALIVE_MILLS))
.setQuery(queryBuilder)
.setSize(SCROLL_BATCH_SIZE_PER_SHARD)// hits per shard will be returned for each scroll
.execute().actionGet();
//Scroll until no hits are returned
while (true) {
if(scrollResp != null){
List<String> hitsList = new ArrayList<>();
for (SearchHit hit : scrollResp.getHits().getHits()) {
hitsList.add(hit.getSourceAsString());
}
callBack.doInScroll(hitsList);
scrollResp = getEsClient().prepareSearchScroll(scrollResp.getScrollId())
.setScroll(new TimeValue(60000)).execute().actionGet();
//Break condition: No hits are returned
if (scrollResp.getHits().getHits().length == 0) {
break;
}
}
}
} catch (Exception e) {
logger.error("err in es doScanWithScroll:",e);
}
}
/**
* 获取每个查询项的列表,可以自行组装更复杂的查询条件
* @param request
* @return
*/
public static List<QueryBuilder> getAllQuery(EsQueryRq request){
List<QueryBuilder> queryList = new ArrayList<>();
queryList.add(getQueryByMatchAllMap(request));
queryList.add(getQueryByMatchOneMap(request));
queryList.add(getQueryByRangeList(request));
return queryList;
}
/**
* 组合所有条件,条件之间是 and 关系
* @param request
* @return
*/
public static QueryBuilder getCompoundQueryWithAnd(EsQueryRq request){
List<QueryBuilder> queryList = getAllQuery(request);
if ( !queryList.isEmpty()){
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
for (QueryBuilder query : queryList){
if (query != null){
bqb = bqb.must(query);
}
}
return bqb;
}
return null;
}
/**
* 组合所有条件,条件之间是 or 关系
* @param request
* @return
*/
public static QueryBuilder getCompoundQueryWithOr(EsQueryRq request){
List<QueryBuilder> queryList = getAllQuery(request);
if (!queryList.isEmpty()){
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
for (QueryBuilder query : queryList){
if (query != null){
bqb = bqb.should(query);
}
}
return bqb;
}
return null;
}