Elasticsearch实战高级搜索 您所在的位置:网站首页 3范式和bc范式区别例子 Elasticsearch实战高级搜索

Elasticsearch实战高级搜索

2023-06-13 17:46| 来源: 网络整理| 查看: 265

一、需求背景:

虽然上一章讲到了完全匹配,但是有些时候查询结果还是很多,关键字在结果中的位置是杂乱的,这样搜索还是不太容易快速定位到自己想要的结果,这一章就是讲搜索结果的相关度排序。

类似如电商搜索:

Elasticsearch实战高级搜索-二次排序_搜索

排序优先级为: 

关键词在结果中出现的位置越靠前,排序越靠前;关键词在结果中的字符占比越高,排序越靠前。

再举个明显的例子,如下搜索“高”,先看“高”在左边的越靠前,然后看“高”字的文本长度占比越高越靠前:

Elasticsearch实战高级搜索-二次排序_脚本_02

为了控制搜索结果的相关度,elasticsearch提供了多种方式,通过脚本实现自定义评分逻辑是终极方式。脚本返回一个评分值,该值再与原_score再进行加法等运算。脚本编写很简单,我们跟随一个例子(基于6.0版本)来看看如何通过脚本实现自定义排序。

二、磨刀霍霍:

搭建本地开发环境(此处省略一万字)。

mapping的定义:

{ "es-type": { "properties": { "line_id": { "type": "long" }, "line_name": { "type": "text", "analyzer": "ngram_analyzer", "fields": { "keyword": { "type": "keyword" } } } } } }

line_name的text字段用于全文本搜索。keyword字段没有分词,用于把搜索结果作为参数传入脚本函数,实现自定义排序逻辑。

写入测试数据:

Elasticsearch实战高级搜索-二次排序_Elasticsearch_03

执行搜索关键字“ip”:

Elasticsearch实战高级搜索-二次排序_数据_04

unction_score查询:是用来控制评分过程的终极武器,它允许为每个与主查询匹配的文档应用一个函数,以达到改变甚至完全替换原始查询评分 _score 的目的。script_score:用自定义脚本完全控制评分计算,实现所需逻辑。lang:指定脚本语言。params:指定作为变量传递到脚本中的任何命名参数。

返回结果:

Elasticsearch实战高级搜索-二次排序_Painless_05

根据排序规则一(关键词在结果中出现的位置越靠前,排序越靠前),"ip流量数据"、"iphone"和"iphone 6s"排在"昨日iphone价格数据"。根据排序规则二(关键词在结果中的字符占比越高,排序越靠前),"ip流量数据"和"iphone"的字符长度是一样的,所以评分一样,而"iphone 6s"字符长度比"iphone"长,“ip”字符占比低,排在后面。

elasticsearch支持多种脚本语言,经历各版本演变后,从5.0开始实现了自己专用的语言:Painless。Groovy已弃用,这次示例使用Painless实现,Painless是内置支持的。下面详细看下脚本代码:

String result = doc['line_name.keyword'].value.toLowerCase(); String keyText = params.keyword.toLowerCase(); double MAX_VALUE = 1000; double position_score = 0; double init = 100; double weight = 0.9; int maxIndex = 0; for (int x = 0; x < keyText.length(); x++) { char ch = keyText.charAt(x); int pos = result.indexOf(ch, maxIndex); if (pos >= 0) { maxIndex = pos; double score = init * (weight); for (int i = 0; i < pos; i++) { score = score * (1 - weight); } position_score = position_score + score; } } double similarity_score = 0; double similarity = Math.abs(1.0 * result.length() - 1.0 * keyText.length()); similarity_score = 10.0 d - similarity; if (similarity_score < 0) { similarity_score = 0; } double total = position_score * MAX_VALUE + similarity_score * 0.1; return total;

获取文档值:doc['line_name.keyword']

传入排序的关键字:params.keyword

实现比较简单,根据位置和字符占比分别计算评分,将结果乘不同权重再相加。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有