ElasticSearch painless脚本实现自定义打分排序

背景:
遇到了这样一个需求,对于历史购买的商品优先排序

自定义打分排序规则
自定义打分规则,其实就是可以根据打分规则进行排序。注意:只能对索引的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"
      }
    }
  ]
}

你可能感兴趣的:(elasticsearch,java,大数据)