ElasticSearch中单个商品按不同区域定价及排序(多字段组合排序) ScriptSortBuilder
产品需求:商品有一个通用价格字段price,该商品可以设置不同区域的价格有不同的价格,如果有些区域没有设置价格,那就是显示通用价格。
一对多,在ElasticSearch索引文件中以map的形式存储区域价格数据,key是区域ID,value是区域价格。没有区域价格的用户要显示通用价格 也就是price字段,所以排序的时候利用price 与区域价格相加的 然后排序的方式,区域价格在存储到es时与通用价格进行了差值处理,所以在区域价格的map中存储的是两者的差。这样有区域价格的用户 与没有区域价格的用户 利用两个字段相加的和就能得到当前用户实际要展示的价格。
可以在匹配到搜索结果后再处理价格从map中取出对应区域的价格返回给前端。但是拉下来有一个问题就是价格排序,按价格升序或者降序后,由于重新赋值了区域价格,这样给前端的数据价格就是乱的。
在搜索参数中已经有用户的区域ID,那么能不能 在es中就按区域价格排序呢,搜了一翻资料后,发现可以在ElasticSearch排序条件中用script来实现。
es中数据如下
1.kibana http请求
get price_demo/_search
{"query":{"match": {
"name": "测试"
}},
"sort":[{
"_script" : {
"script" : {
"source" : " return doc['price'].value + (doc.containsKey('regionPriceVarianceMap.900097.keyword')?(doc['regionPriceVarianceMap.900097.keyword'].size()==0?0:doc['regionPriceVarianceMap.900097.keyword'].value):0)",
"lang" : "painless"
},
"type" : "number",
"order" : "asc"
}
}
]
}
2java代码,代码中判断了当前区域字段是否存在,不存在则默认为0
private void setSort(NativeSearchQueryBuilder searchQueryBuilder, SearchParameter param) {
if (param.getSortType() == null || param.getSortType().equals(0)) {
//综合排序(设置的sort字段降序,价格升序)
searchQueryBuilder.withSort(SortBuilders.fieldSort(EsProductFields.SORT).order(SortOrder.DESC));
searchQueryBuilder.withSort(getScriptSortBuilder(param).order(SortOrder.ASC));
}
}
public ScriptSortBuilder getScriptSortBuilder(SearchParameter param) {
Long buyerDistrictId = param.getBuyerDistrictId() == null ? 0L : param.getBuyerDistrictId();
StringBuilder sb=new StringBuilder();
sb.append(" double price=doc['price'].value; ");
sb.append(" double districtPrice=0; ");
sb.append(" if(doc.containsKey('regionPriceVarianceMap."+ buyerDistrictId + "'))");
sb.append(" && doc['regionPriceVarianceMap." + buyerDistrictId + "'].size()!=0 { ");
sb.append(" districtPrice=doc['regionPriceVarianceMap." + buyerDistrictId + "'].value;");
sb.append(" } ");
sb.append(" return price+districtPrice; ");
Script script = new Script(sb.toString());
ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER);
return scriptSortBuilder;
}
//需求变动新改
public ScriptSortBuilder getScriptSortBuilder(SearchParameter param) { Long buyerDistrictId = param.getBuyerDistrictId() == null ? 0L : param.getBuyerDistrictId(); String regionKey = "regionPriceVarianceMap." + buyerDistrictId; StringBuilder sb = new StringBuilder(); if (param.getBuyerType() != null && param.getBuyerType() > 0) { String buyerTypePriceKey = "buyerTypePriceMap." + param.getBuyerType(); sb.append(" double price=doc['price'].value;"); sb.append(" if(doc.containsKey('buyerTypePriceMap') && doc.containsKey('" + buyerTypePriceKey + "') && doc['" + buyerTypePriceKey + "'].size()>0){"); sb.append(" price=doc['" + buyerTypePriceKey + "'].value }else{ "); sb.append(" if( doc.containsKey('" + regionKey + "') && doc['" + regionKey + "'].size()>0){"); sb.append(" price = price + doc['" + regionKey + "'].value }"); sb.append("} return price;"); } else { sb.append(" double price=doc['price'].value;"); sb.append(" if( doc.containsKey('" + regionKey + "') && doc['" + regionKey + "'].size()>0){"); sb.append(" price = price + doc['" + regionKey + "'].value } return price;"); } Script script = new Script(sb.toString()); ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER); return scriptSortBuilder; }
本文来自博客园,作者:清玄-2012,转载请注明原文链接:https://www.cnblogs.com/happy-tears/p/15628381.html