目录
1.目的
2.maven依赖
3.通用查询语句生成代码
使用一种通用查询语句,方便其他服务调用es搜索,通用查询参数同阿里云的开放搜索openSearch参数一致(1.公司搜索原来使用的就是阿里云的开放搜索,其它业务不用怎么修改就替换了 2.阿里云的开放搜索语句和参数设计的比较完善,毕竟对方是专业并收费的)
{
"dataAmount": "10",
"andFilter": "min_amount<=50,display_start_date<=1632728060134,(display_end_date='' OR display_end_date>=1632728060134),",
"searchParam": "(platform_type:'1' OR platform_type:'3') AND default:'5473' AND is_active:'2' AND item_type:'2' AND (item_state:'6' OR item_state:'7')",
"dataStart": "0",
"sort": "pay_amount:DECREASE;shelves_date:DECREASE"
}
参数说明:
dataStart:起始行 dataAmount:页大小 searchParam:模糊搜索参数 andFilter:过滤参数 sort:排序参数
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.5.2
org.elasticsearch
elasticsearch
7.5.2
org.elasticsearch.client
elasticsearch-rest-client
7.5.2
org.projectlombok
lombok
true
package com.ybjdw.messageserve.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ybjdw.base.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* author: zhanggw
* 创建时间: 2021/9/27
*/
public class SearchUtil {
private final static Logger logger = LoggerFactory.getLogger(SearchUtil.class);
public final static String OPERATOR_GTE = ">=";
public final static String OPERATOR_LTE = "<=";
public final static String OPERATOR_NET = "!=";
public final static String OPERATOR_GT = ">";
public final static String OPERATOR_ET = "=";
public final static String OPERATOR_LT = "<";
public final static String OPERATOR_AND = "AND";
public final static String OPERATOR_OR = "OR";
private final static List OPERATOR_LIST = new ArrayList<>(Arrays.asList(OPERATOR_GTE,OPERATOR_LTE,OPERATOR_NET,OPERATOR_GT,OPERATOR_ET,OPERATOR_LT));
public final static List FIELD_DATE_LIST = new ArrayList<>(Arrays.asList("displayStartDate","displayEndDate","createDate","modifyDate",OPERATOR_ET,OPERATOR_LT));
/**
* <一句话功能简述> 生成通用es查询
* <功能详细描述>
*{
* "dataAmount": "10",
* "andFilter": "display_start_date<=1632624039672,(display_end_date=0 OR display_end_date>=1632624039672),",
* "searchParam": "default:'6018' AND is_active:'2' AND item_type:'2' AND item_state:'6'",
* "dataStart": "0",
* "sort": "pay_amount:DECREASE;shelves_date:DECREASE"
* }
* author: zhanggw
* 创建时间: 2021/9/27
*/
public static SearchSourceBuilder generateEsQuery(JSONObject searchTermJson){
try{
if(searchTermJson == null){
return null;
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 总查询条件
BoolQueryBuilder topQuery = QueryBuilders.boolQuery();
// 模糊搜索添加参数
matchAddSearchParam(topQuery, searchTermJson.getString("searchParam"));
// 精确搜索添加参数
termAddSearchParam(topQuery, searchTermJson.getString("termParam"));
// 添加过滤器
String filterParamStr = searchTermJson.getString("andFilter");
queryAddFilter(topQuery, filterParamStr);
sourceBuilder.query(topQuery);
// 添加分页
Integer dataStartInteger = searchTermJson.getInteger("dataStart");
Integer dataAmountInteger = searchTermJson.getInteger("dataAmount");
if(dataStartInteger != null){
sourceBuilder.from(dataStartInteger);
}
if(dataAmountInteger != null){
sourceBuilder.size(dataAmountInteger);
}
// 添加展示字段
String showFieldStr = searchTermJson.getString("showFields");
String excludeFieldStr = searchTermJson.getString("excludeFields");
searchAddShowField(sourceBuilder, showFieldStr, excludeFieldStr);
// 添加排序
queryAddSort(sourceBuilder, searchTermJson.getString("sort"));
return sourceBuilder;
}catch (Exception e){
logger.error("生成通用es查询异常!", e);
}
return null;
}
/**
* <一句话功能简述> 在BoolQueryBuilder上添加展示字段
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/11/5
*/
private static void searchAddShowField(SearchSourceBuilder sourceBuilder, String showFieldStr, String excludeFieldStr) {
try{
String[] showFieldArray = null;
if(showFieldStr != null){
showFieldArray = showFieldStr.split(",");
showFieldArray = camelCaseNameArray(showFieldArray);
}
String[] excludeFieldArray = null;
if(excludeFieldStr != null){
excludeFieldArray = excludeFieldStr.split(",");
excludeFieldArray = camelCaseNameArray(excludeFieldArray);
}
sourceBuilder.fetchSource(showFieldArray, excludeFieldArray);
}catch (Exception e){
logger.error("查询添加展示字段异常!", e);
}
}
private static String[] camelCaseNameArray(String[] showFieldArray) {
try{
if(showFieldArray == null || showFieldArray.length == 0){
return showFieldArray;
}
String[] newFieldArray = new String[showFieldArray.length];
for(int i=0; i < showFieldArray.length; i++){
newFieldArray[i] = camelCaseName(showFieldArray[i]);
}
return newFieldArray;
}catch (Exception e){
logger.error("转换字符串数组驼峰异常!", e);
return showFieldArray;
}
}
/**
* <一句话功能简述> 在BoolQueryBuilder中添加模糊匹配
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param searchParamStr 模糊搜索参数 (platform_type:'1' OR platform_type:'3') AND default:'5473' AND is_active:'2' AND item_type:'2' AND (item_state:'6' OR item_state:'7')
*/
private static void matchAddSearchParam(BoolQueryBuilder topQuery, String searchParamStr) {
try{
if(topQuery == null || StringUtils.isBlank(searchParamStr)){
return;
}
logger.trace("BoolQueryBuilder开始添加模糊搜索参数,searchParam:{}", searchParamStr);
String[] searchParamArray = searchParamStr.split(OPERATOR_AND);
if(searchParamArray.length > 0){
for(String searchParam:searchParamArray){ // 第一层and filter
searchParam = searchParam.trim();
if(StringUtils.isBlank(searchParam)){
continue;
}
if(searchParam.contains("OR")){ // 搜索带or
searchParam = searchParam.replace("(","").replace(")","");
String[] orMatchArray = searchParam.split(OPERATOR_OR);
if(orMatchArray.length > 0){
logger.trace("or match,searchParam:{}", searchParam);
BoolQueryBuilder orMatchQuery = QueryBuilders.boolQuery();
for(String orSubMatch:orMatchArray){
QueryBuilder matchQuery = getMatchQuery(orSubMatch);
if(matchQuery != null){
orMatchQuery.should(matchQuery);
}
}
topQuery.must(orMatchQuery);
}
}else{
QueryBuilder matchQuery = getMatchQuery(searchParam);
if(matchQuery != null){
topQuery.must(matchQuery);
}
}
}
}
}catch (Exception e){
logger.error("topQuery添加过滤条件异常!", e);
}
}
/**
* <一句话功能简述> 在BoolQueryBuilder中添加精确匹配
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param termParamStr 精确搜索参数 (platform_type:'1' OR platform_type:'3') AND default:'5473' AND is_active:'2' AND item_type:'2' AND (item_state:'6' OR item_state:'7')
*/
private static void termAddSearchParam(BoolQueryBuilder topQuery, String termParamStr) {
try{
if(topQuery == null || StringUtils.isBlank(termParamStr)){
return;
}
logger.trace("BoolQueryBuilder开始添加精确搜索参数,termParamStr:{}", termParamStr);
String[] termParamArray = termParamStr.split(OPERATOR_AND);
if(termParamArray.length > 0){
for(String termParam:termParamArray){ // 第一层and filter
termParam = termParam.trim();
if(StringUtils.isBlank(termParam)){
continue;
}
if(termParam.contains("OR")){ // 搜索带or
termParam = termParam.replace("(","").replace(")","");
String[] orTermArray = termParam.split(OPERATOR_OR);
if(orTermArray.length > 0){
logger.trace("or term,termParam:{}", termParam);
BoolQueryBuilder orTermQuery = QueryBuilders.boolQuery();
for(String orSubTerm:orTermArray){
QueryBuilder termQuery = getTermQuery(orSubTerm);
if(termQuery != null){
orTermQuery.should(termQuery);
}
}
topQuery.must(orTermQuery);
}
}else{
QueryBuilder termQuery = getTermQuery(termParam);
if(termQuery != null){
topQuery.must(termQuery);
}
}
}
}
}catch (Exception e){
logger.error("topQuery添加过滤条件异常!", e);
}
}
/**
* <一句话功能简述> 在BoolQueryBuilder中添加过滤条件
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param andFilterStr "display_start_date<=1632624039672,(display_end_date='' OR display_end_date>=1632624039672),",
*/
private static void queryAddFilter(BoolQueryBuilder topQuery, String andFilterStr) {
try{
if(topQuery == null || StringUtils.isBlank(andFilterStr)){
return;
}
logger.trace("BoolQueryBuilder开始添加过滤条件,andFilterStr:{}", andFilterStr);
String[] filterConditionArray = andFilterStr.split(",");
if(filterConditionArray.length > 0){
for(String filterCondition:filterConditionArray){ // 第一层and filter
filterCondition = filterCondition.trim();
if(StringUtils.isBlank(filterCondition)){
continue;
}
filterCondition = filterCondition.replace("or", OPERATOR_OR);
if(filterCondition.contains(OPERATOR_OR)){ // 过滤中带or
filterCondition = filterCondition.replace("(","").replace(")","");
String[] orFilterArray = filterCondition.split(OPERATOR_OR);
if(orFilterArray.length > 0){
BoolQueryBuilder orFilterQuery = QueryBuilders.boolQuery();
for(String orSubFilter:orFilterArray){
orFilterQuery.should(getFilterQuery(orSubFilter));
}
topQuery.filter(orFilterQuery);
}
}else{
topQuery.filter(getFilterQuery(filterCondition));
}
}
}
}catch (Exception e){
logger.error("topQuery添加过滤条件异常!", e);
}
}
/**
* <一句话功能简述> 过滤基本语句转化
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param filterParamBasic 过滤基本语句 display_start_date<=1632624039672
*/
private static QueryBuilder getFilterQuery(String filterParamBasic) {
QueryBuilder queryBuilder = null;
for(String operator:OPERATOR_LIST){
if(filterParamBasic.contains(operator)){
String[] filterArray = filterParamBasic.split(operator);
String filterName = camelCaseName(filterArray[0]);
filterName = filterName.trim();
String filterValue = filterArray[1];
filterValue = processFilterParam(filterName, filterValue); // 处理过滤参数,业务相关
logger.trace("filterParamBasic:{},filterName:{},filterValue:{}", filterParamBasic,filterName, filterValue);
switch (operator){
case SearchUtil.OPERATOR_GTE:
queryBuilder = QueryBuilders.rangeQuery(filterName).gte(filterValue);
break;
case SearchUtil.OPERATOR_NET:
if(StringUtils.isBlank(filterValue)){
queryBuilder = QueryBuilders.existsQuery(filterName);
}else{
queryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(filterName, filterValue));
}
break;
case SearchUtil.OPERATOR_LTE:
queryBuilder = QueryBuilders.rangeQuery(filterName).lte(filterValue);
break;
case SearchUtil.OPERATOR_GT:
queryBuilder = QueryBuilders.rangeQuery(filterName).gt(filterValue);
break;
case SearchUtil.OPERATOR_ET:
if(StringUtils.isBlank(filterValue)){
queryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(filterName));
}else{
queryBuilder = QueryBuilders.termQuery(filterName, filterValue);
}
break;
case SearchUtil.OPERATOR_LT:
queryBuilder = QueryBuilders.rangeQuery(filterName).lt(filterValue);
break;
}
break;
}
}
return queryBuilder;
}
private static String preProcessFilter(String filterParamStr) {
try{
filterParamStr = filterParamStr.replace("display_end_date=0", "display_end_date=''");
}catch (Exception e){
logger.error("es过滤参数预处理异常!", e);
}
return filterParamStr;
}
/**
* <一句话功能简述> 处理过滤参数
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/10/12
*/
private static String processFilterParam(String filterName, String filterValue) {
try{
// 去掉单引号和空格
filterValue = filterValue.replace("'","");
filterValue = filterValue.trim();
// 处理日期字段
if(FIELD_DATE_LIST.contains(filterName)){
if("0".equals(filterValue)){ // 时间为0表示空
return "";
}
if(StringUtils.isNotBlank(filterValue)){ // 由于存入es中的时间字符串没加时区,默认不是东八区,查询时间参数需延后8小时
Date dateVal = new Date();
dateVal.setTime(Long.parseLong(filterValue));
logger.trace("dateVal:{}", dateVal);
dateVal = DateUtils.timeCalendar(dateVal, 8, 0, 0);
logger.trace("dateVal:{}", dateVal);
filterValue = dateVal.getTime()+"";
return filterValue;
}
}
}catch (Exception e){
logger.error("处理过滤器参数异常!");
}
return filterValue;
}
/**
* <一句话功能简述> 模糊搜索参数转化
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param searchParamBasic 模糊搜索参数 is_active:'2'
*/
private static QueryBuilder getMatchQuery(String searchParamBasic) {
try{
if(StringUtils.isBlank(searchParamBasic)){
return null;
}
int separateIndex = searchParamBasic.indexOf(":");
String fieldName = camelCaseName(searchParamBasic.substring(0, separateIndex));
String fieldValue = searchParamBasic.substring(separateIndex);
fieldValue = fieldValue.replace("'","").replace(":","");
fieldName = fieldName.trim().replace("(","");
fieldValue = fieldValue.trim().replace(")","");
logger.debug("searchParamBasic:{},fieldName:{},fieldValue:{}", searchParamBasic, fieldName, fieldValue);
MatchQueryBuilder matchQueryBuilder = null;
if(fieldValue.contains("^")){
try{
String[] valueArray = fieldValue.split("\\^");
matchQueryBuilder = QueryBuilders.matchQuery(fieldName, valueArray[0]);
matchQueryBuilder.boost(Integer.parseInt(valueArray[1]));
}catch (Exception e){
logger.error("elasticSearch boost设置异常!");
String[] valueArray = fieldValue.split("\\^");
matchQueryBuilder = QueryBuilders.matchQuery(fieldName, valueArray[0]);
}
}else{
matchQueryBuilder = QueryBuilders.matchQuery(fieldName, fieldValue);
}
return matchQueryBuilder;
}catch (Exception e){
logger.error("getMatchQuery error!", e);
}
return null;
}
/**
* <一句话功能简述> 精确搜索参数转化
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param termParamBasic 模糊搜索参数 is_active:'2'
*/
private static QueryBuilder getTermQuery(String termParamBasic) {
try{
if(StringUtils.isBlank(termParamBasic)){
return null;
}
int separateIndex = termParamBasic.indexOf(":");
String fieldName = camelCaseName(termParamBasic.substring(0, separateIndex));
String fieldValue = termParamBasic.substring(separateIndex);
fieldValue = fieldValue.replace("'","").replace(":","");
fieldName = fieldName.trim();
fieldValue = fieldValue.trim();
logger.trace("termParamBasic:{},fieldName:{},fieldValue:{}", termParamBasic, fieldName, fieldValue);
return QueryBuilders.termQuery(fieldName, fieldValue);
}catch (Exception e){
logger.error("getTermQuery error!", e);
}
return null;
}
/**
* <一句话功能简述> 含下划线字符串转换为驼峰式字符串
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
*/
public static String camelCaseName(String underscoreName) {
if(StringUtils.isBlank(underscoreName) || !underscoreName.contains("_")){
return underscoreName;
}
StringBuilder result = new StringBuilder();
boolean flag = false;
for (int i = 0; i < underscoreName.length(); i++) {
char ch = underscoreName.charAt(i);
if ("_".charAt(0) == ch) {
flag = true;
} else {
if (flag) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
result.append(ch);
}
}
}
return result.toString();
}
/**
* <一句话功能简述> 查询添加排序参数
* <功能详细描述>
* author: zhanggw
* 创建时间: 2021/9/27
* @param sortStr pay_amount:DECREASE;shelves_date:DECREASE
*/
private static void queryAddSort(SearchSourceBuilder sourceBuilder, String sortStr) {
try{
if(StringUtils.isBlank(sortStr)){
return;
}
String[] sortArray = sortStr.split(";");
if(sortArray.length > 0){
for(String sortSubParam:sortArray){
String[] sortSubParamArray = sortSubParam.split(":");
String sortFieldName = sortSubParamArray[0];
String fieldValue = sortSubParamArray[1];
SortOrder sortOrder = SortOrder.DESC; // 默认降序 DECREASE
if("INCREASE".equals(fieldValue)){
sortOrder = SortOrder.ASC;
}
if("_score".equalsIgnoreCase(sortFieldName)){ // 指定评分排序
sourceBuilder.sort(new FieldSortBuilder("_score").order(sortOrder));
}else{ // 非评分排序会进行驼峰转换
String fieldName = camelCaseName(sortFieldName);
sourceBuilder.sort(new FieldSortBuilder(fieldName).order(sortOrder));
}
}
}
}catch (Exception e){
logger.error("查询添加排序参数异常!", e);
}
}
public static void main(String[] args) {
String query = "{\"dataAmount\":\"24\",\"andFilter\":\"display_start_date<=1634017236255,(display_end_date>=1634017236255 OR display_end_date=0),\",\"searchParam\":\"company_id:'020001015880652390500000' AND goods_class:'110000' AND is_active:'2' AND item_state:'6'\",\"dataStart\":\"0\",\"sort\":\"seven_sales:DECREASE;shelves_date:DECREASE\"}";
query = "{\"dataAmount\":\"10\",\"andFilter\":\"display_start_date<=1634022646464,(display_end_date>=1634022646464 OR display_end_date=0),\",\"searchParam\":\"default:'1090' AND is_active:'2' AND item_type:'2' AND item_state:'6'\",\"dataStart\":\"0\",\"sort\":\"pay_amount:DECREASE;shelves_date:DECREASE\"}";
query = "{\"dataAmount\":\"6\",\"andFilter\":\"info_state=5\",\"searchParam\":\"(default:'测试' OR info_name:'测试' OR company_name:'测试' OR info_content:'测试')\",\"dataStart\":\"0\",\"sort\":\"is_top:DECREASE;refresh_date:DECREASE;pass_date:DECREASE\",\"showFields\":\"info_id,info_name,info_type,second_type,start_date,end_date,province,city,region,address,info_banner,info_content,info_picture,info_url,contact_info,enroll_type,invite_type,info_state,fail_reasion,company_id,company_name,company_abbr,company_logo,company_type,user_id,enroll_num,scan_num,pass_date,modify_date,create_date,remarks,is_top,refresh_date,user_type\"}";
query = "{\"dataAmount\":\"6\",\"andFilter\":\"info_state=5\",\"searchParam\":\"(default:'测试'^30 OR info_name:'测试'^100 OR company_name:'测试'^80 OR info_content:'测试'^10)\",\"dataStart\":\"0\",\"sort\":\"is_top:DECREASE;refresh_date:DECREASE;pass_date:DECREASE\",\"showFields\":\"info_id,info_name,info_type,second_type,start_date,end_date,province,city,region,address,info_banner,info_content,info_picture,info_url,contact_info,enroll_type,invite_type,info_state,fail_reasion,company_id,company_name,company_abbr,company_logo,company_type,user_id,enroll_num,scan_num,pass_date,modify_date,create_date,remarks,is_top,refresh_date,user_type\"}";
SearchSourceBuilder searchSourceBuilder = generateEsQuery(JSON.parseObject(query));
logger.debug("searchSourceBuilder:{}", searchSourceBuilder);
}
}
运行main方法生成的es查询语句为:
{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [{
"bool": {
"should": [{
"match": {
"platformType": {
"query": "1 ",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}, {
"match": {
" platformType": {
"query": "3",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
}, {
"match": {
"default": {
"query": "5473",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}, {
"match": {
"isActive": {
"query": "2",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}, {
"match": {
"itemType": {
"query": "2",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}, {
"bool": {
"should": [{
"match": {
"itemState": {
"query": "6 ",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}, {
"match": {
" itemState": {
"query": "7",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
}],
"filter": [{
"range": {
"minAmount": {
"from": null,
"to": "50",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
}, {
"range": {
"displayStartDate": {
"from": null,
"to": "1632728060134",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
}, {
"bool": {
"should": [{
"bool": {
"must_not": [{
"exists": {
"field": "displayEndDate",
"boost": 1.0
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
}, {
"range": {
" displayEndDate": {
"from": "1632728060134",
"to": null,
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
}],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"sort": [{
"payAmount": {
"order": "desc"
}
}, {
"shelvesDate": {
"order": "desc"
}
}]
}
使用kibana运行es查询语句