背景:
遇到了这样一个需求,对于历史购买的商品优先排序
自定义打分排序规则
自定义打分规则,其实就是可以根据打分规则进行排序。注意:只能对索引的keyword属性进行排序,TEXT类型的要加.keyWord,如:doc[‘索引列名.keyword’].value
需求背景:
查出来的某个字段的值等于或包含某些字符时,优先排序。
一、全匹配排序
例子:对历史购买商品优先排序
java代码实现:
其实就是拼接出painless脚本,通过NativeSearchQueryBuilder进行排序,然后通过springDataES带的search方法进行查询。
(doc[‘索引列名’].value==(‘要匹配的值’))?1000002:(doc[‘索引列名’].value==(‘要匹配的值’))?1000001:"
三目运算法中?后面跟的数值,就是权重值,权重越大,排序越靠前
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.withIndices(getIndexName(ProductIndex.class))
.withTypes(getType(ProductIndex.class))
.withPageable(pageIndexRequest.toPageable())
.withFilter(boolQueryBuilder);
StringBuffer buffer = new StringBuffer();
//此处拼接painless脚本,1000000为权重
int num = historyBuyProductCodeList.size() + 1000000;
for (int i = 0; i < historyBuyProductCodeList.size(); i++) {
buffer.append("(doc['索引列名'].value=='" + historyBuyProductCodeList.get(i) + "')?" + num + ":");
num--;
if (i == historyBuyProductCodeList.size() - 1) {
buffer.append("0");
break;
}
}
String historyProductScriptText = buffer.toString().trim();
//我们不需要参数,所以传个没有键值对的对象进去就可以了
Map<String, Object> params = new HashMap<>();
Script script = new Script(ScriptType.INLINE, "painless", historyProductScriptText, params);
ScriptSortBuilder sortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);
nativeSearchQueryBuilder.withSort(sortBuilder);
//进行查询
SearchQuery searchQuery = nativeSearchQueryBuilder.withSort(order).build();
Page<ProductIndex> page = productIndexRepository.search(searchQuery);
restful请求实现:
GET /索引名称/_search
{
"query": {
"match_all": {}
},
"from": 0, // 分页开始的位置,默认为0
"size": 1000,
"sort": [
{
"_script": {
"script": {
"source": "(doc['索引列名'].value==('要匹配的值'))?1000002:(doc['索引列名'].value==('要匹配的值'))?1000001:",
"lang": "painless"
},
"type": "number",
"order": "desc"
}
}
]
}
二、模糊匹配排序
java代码实现:
StringBuffer buffer = new StringBuffer();
int num = warehouseIds.size() + 10000;
for (int i = 0; i < warehouseIds.size(); i++) {
//注意,这里是contains来实现的
buffer.append("(doc['索引列名'].value.contains('" + warehouseIds.get(i) + "'))?" + num + ":");
num--;
if (i == warehouseIds.size() - 1) {
buffer.append("0");
break;
}
}
String stockScriptText = buffer.toString().trim();
Map<String, Object> params = new HashMap<>();
Script stockScript = new Script(ScriptType.INLINE, "painless", stockScriptText, params);
ScriptSortBuilder sortBuilder = SortBuilders.scriptSort(stockScript, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);
nativeSearchQueryBuilder.withSort(sortBuilder);
//进行查询
SearchQuery searchQuery = nativeSearchQueryBuilder.withSort(order).build();
Page<ProductIndex> page = productIndexRepository.search(searchQuery);
restful请求实现:
GET /索引名称/_search
{
"query": {
"match_all": {}
},
"from": 0, // 分页开始的位置,默认为0
"size": 1000,
"sort": [
{
"_script": {
"script": {
"source": "(doc['索引列名'].value.contains('要匹配的值'))?10002:(doc['索引列名'].value.contains('要匹配的值'))?10001:",
"lang": "painless"
},
"type": "number",
"order": "desc"
}
}
]
}