ElasticSearch的劈山斧-自定义评分

devtools/2025/1/18 2:50:11/

ElasticSearch自定义评分

一、适用的场景

1.基本介绍

ES的使用中,ES会对我们匹配文档进行相关度评分。但对于一些定制化的场景,默认评分规则满足不了我们的要求。这些定制化场景,ES也是推出了自定义评分方式来进行支持。可以使用ES提供的一些函数,什么可以使用较分来让我们的评分规则多样化我举个大家都很熟悉的场景,在点外卖时候,大家是不是有一个综合排序,比如用户希望通过距离和价格来进行综合排序,这在mysql中是不是比较难以实现,接下来我将由简到繁的来教你如何在ES中实现这种综合评分排序的功能

2.使用场景

2.1根据价格评分排序

在mysql中我们可以通过价格从高到低,从低到高排序,但是像订酒店那样,用户有期望价格的,酒店越符合用户的期望价格,评分越高。mysql的排序这时候是不是有点捉襟见肘了。废话不多说了,直接来ES实现。

java">{"from": 0,"size": 12,"query": {"function_score": {"query": {"bool": {"must": [{"term": {"price": {"value": 50,"boost": 1.0}}}],"adjust_pure_negative": true,"boost": 1.0}},"functions": [{"filter": {"match_all": {"boost": 1.0}},"gauss": {"price": {"origin": 50,"offset": 0,"scale": "25","decay": 0.5}}}]}},"sort": [{"_score": {"order": "desc"}}]}
2.2根据距离评分排序

在我们日常使用的场景,我们经常有需要根据距离来进行排序评分,常见的App中都是有一个距离更近,来筛选商户。接下来就来看看ES的实现。

java">{"from": 0,"size": 12,"query": {"function_score": {"query": {"bool": {"must": [{"term": {"price": {"value": 50,"boost": 1.0}}}],"adjust_pure_negative": true,"boost": 1.0}},"functions": [{"filter": {"match_all": {"boost": 1.0}},"gauss": {"location": {"origin": {"lon": 130.380857,"lat": 31.112834},"offset": 0,"scale": "150km","decay": 0.5}}}]}},"sort": [{"_score": {"order": "desc"}}]}
2.3根据距离价格综合评分排序

上面举例了两个单一的场景,要么是价格,要么是距离,那如果想实现复杂点的场景呢,希望通过距离和价格综合排序。比如用户希望订一个距离虹桥火车站近的,价格200左右的酒店。废话不多说,直接看实现。

java">{"from": 0,"size": 12,"query": {"function_score": {"query": {"match_all": {"boost": 1.0}},"functions": [{"filter": {"match_all": {"boost": 1.0}},"gauss": {"location": {"origin": {"lon": 130.380857,"lat": 31.112834},"scale": "150km","decay": 0.5},"multi_value_mode": "MIN"},"weight": 1},{"filter": {"match_all": {"boost": 1.0}},"gauss": {"price": {"origin": 200,"offset": 0,"scale": "25","decay": 0.5}},"weight": 2}],"score_mode": "sum","boost_mode": "replace","max_boost": 3.4028235E38,"boost": 1.0}},"sort": [{"_score": {"order": "desc"}}]}
2.4自定义编写脚本

像上面都是ES提供给我们现成的功能函数,但是,用户的场景千千万,总有一个场景这些函数会不适合。比如,用户希望酒店的价格的结尾含8的评分更高呢。ES提供的这些函数就不起作用了,但ES还提供了终极密法。你可以自定义脚本来决定每个文档的分数。

java">{"from": 0,"size": 12,"query": {"function_score": {"query": {"bool": {"must": [{"term": {"price": {"value": 50,"boost": 1.0}}}],"adjust_pure_negative": true,"boost": 1.0}},"functions": [{"filter": {"match_all": {"boost": 1.0}},"script_score": {"script": {"source": "doc['price'].size()==0?0:5","lang": "painless"}}}],"score_mode": "sum","boost_mode": "replace","max_boost": 3.4028235E38,"boost": 1.0}},"sort": [{"_score": {"order": "desc"}}]}

二、常用的字段解释

1.整体结构

如果需要使用自定义评分,评分查询结构和正常的查询结构还是有些区别的,分页和排序和正常的都是一样的,主要还是query内的成员,使用的是function_score。我们来看看图上框住的就是自定义评分需要使用的特定的查询结构。看看里面是不是还有很多成员,接下来我一一为大家介绍这些成员的含义。

2.function_score

2.1 query

function_score第一个成员query,这个就和大家平时用的一样,筛选符合条件的结果,并把这个结果用作后面的评分函数的数据来源,我们来看看它内部的结构。下图框中,目的是为了查询price为50的结果

2.2 functions

functions,也是我们使用评分函数和编写脚本的地方,他的值是一个数组,也就是我们使用多个函数来进行综合评分,还可以对每个评分进行权重控制,主要有以下几个值

  filter:filter主要通过条件匹配结果作用在当前函数上

  weight:weight当前函数的权重,函数的分值会乘上weight

ES提供的几种评分模式,是脚本还是随机等

1. 衰减函数:

先看看官方的图,衰减函数的作用机制,我们可以设定一个期望值,越接近期望值的分越高,分值在0-1之间,分别有三条对应的函数曲线linear 、 exp 和 gauss (线性、指数和高斯函数)

原点(origin):期望值,这个值可以得到满分(1.0)

偏移量(offset):与原点相差在偏移量之内的值也可以得到满分

衰减规模(scale):当值超出了原点到偏移量这段范围,它所得的分数就开始进行衰减了,衰减规模需配合衰减值一起使用。比如衰减规模是500米,衰减值是0.5,那么在500米的时候分值就是0.5,具体衰减速率由函数曲线决定

衰减值(decay):该字段可以被接受的值(默认为 0.5),相当于一个分界点,具体的效果与衰减的模式有关

2. script_score:自定义脚本评分,主要就是我们编写脚本的地方

描述

source

就是我们需要填写脚本的地方

lang

使用的脚本语言,几个可选值对应相应的开发语言

3. random_score:随机得到 0 到 1 分数

4. field_value_factor:将某个字段的值进行计算得出分数。

2.3 score_mode

score_mode,主要是控制我们多个评分函数之间如何运算的,比如function_score第一个元素会对结果进行评分,第二元素也会对结果进行评分,我们通过参数来控制这两个的评分是相加还是别的操作,这最终得出来的分值也称为功能分值。有以下几个可选值

函数名称

描述

max

使用最高分

first

使用第一个评分函数的分值

multiply

多个评分函数分值相乘(默认)

avg

多个评分函数分值的平均值

sum

多个评分函数分值的分数和

min

使用最小分

2.4 boost_mode

boost_mode,控制的是查询分值(下图框起来的1的部分)和功能分值(下图框起来的2的部分)是如何运算的。有以下几个可选值

函数名称

描述

max

使用查询分数和功能分数里最大值

replace

使用功能分数,查询分数将被忽略

multiply

使用查询分数和功能分数相乘(默认)

avg

使用查询分数和功能分数平均值

sum

使用查询分数和功能分数和

min

使用查询分数和功能分数里最小值

三、通过ESJavaApi实现自定义评分功能

java">public static void main(String[] args) {/**构建functions**/FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[2];//第一个评分函数,gaussMap<String, Double> locationMap = new HashMap<String, Double>();locationMap.put("lat", 130.11);locationMap.put("lon", 12.12);ScoreFunctionBuilder gaussFunctionByLocation = ScoreFunctionBuilders.gaussDecayFunction("location", locationMap, "150km", 0, 0.5);filterFunctionBuilders[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(gaussFunctionByLocation);//第二个评分函数,自定义评分String scriptLang = "painless";String script = "doc['price'].size()==0?0:5";ScriptScoreFunctionBuilder scriptFunction = ScoreFunctionBuilders.scriptFunction(new Script(Script.DEFAULT_SCRIPT_TYPE, scriptLang, script, Collections.emptyMap(), Collections.emptyMap()));filterFunctionBuilders[1] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(scriptFunction);/**function_score**///构建queryBoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//设置query,functionsFunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(boolQueryBuilder, filterFunctionBuilders);//设置boostModefunctionScoreQueryBuilder.boostMode(CombineFunction.REPLACE);//设置scoreModefunctionScoreQueryBuilder.scoreMode(FunctionScoreQuery.ScoreMode.SUM);//设置分页排序SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.from(0);sourceBuilder.size(12);sourceBuilder.sort("price", SortOrder.ASC);//执行SearchRequest searchRequest = new SearchRequest("index_name");searchRequest.source(sourceBuilder);}

http://www.ppmy.cn/devtools/151441.html

相关文章

Go语言之路————条件控制:if、for、switch

Go语言之路————if、for、switch 前言ifforswitchgoto和label 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#xff0c;到后面能正常完成工作上的业务开发的过程&#xff0…

大模型——RAG

什么是RAG RAG&#xff08;Retrieval Augmented Generation,检索增强生成&#xff09;&#xff0c;LLM在回答问题或生成文本时&#xff0c;先会从大量文档中检索出相关的信息&#xff0c;然后基于这些信息生成回答或文本&#xff0c;从而提高预测质量。 R:检索器模块 在RAG中…

云手机技术怎么实现的?

前言 随着亚矩阵云手机在跨境电商、海外社媒矩阵搭建、出海运营、海外广告投放、国内新媒体矩阵运营、品牌应用矩阵运营等领域内的普及和使用&#xff0c;云手机的理念已经被越来越多人所接受和认同。今天我们就一起来浅析一下&#xff0c;到底云手机的技术是怎么实现的&#…

windows安装docker

安装 首先确保windows启用Hyper-V&#xff0c;子linux系统和虚拟机平台&#xff0c;且cpu开启虚拟化 重启等待应用生效 安装doxker desktop 下载链接 打开cmd&#xff0c;输入docker version查看安装情况 在服务类型查看docker服务是否启动&#xff0c;不是进入服务修改为自…

LDN的蓝牙双模键盘帮助文档

文档索引 已支持的PCB列表(仅列出少部分)&#xff1a;键盘特性硬件软件键盘以及驱动蓝牙模式USB模式 驱动功能介绍主界面键盘列表页面键盘配置&#xff08;使用双模键盘的请务必细看本说明&#xff09;功能层配置(改键)触发层配置(改FN键等触发功能)功能选择&#xff08;重要&a…

MyBatis——XML映射文件

在MyBatis中&#xff0c;既可以通过注解的方式配置SQL语句&#xff0c;也可以通过XML映射文件的方式配置SQL语句。对于简单的SQL语句建议直接通过注解的方式配置SQL语句&#xff1a; Delete("delete from user where id#{id}") Integer deleteById(Integer id);但是…

RabbitMQ中有哪几种交换机类型?

大家好&#xff0c;我是锋哥。今天分享关于【RabbitMQ中有哪几种交换机类型&#xff1f;】面试题。希望对大家有帮助&#xff1b; RabbitMQ中有哪几种交换机类型&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在RabbitMQ中&#xff0c;交换机&#xf…

【人工智能】大语言模型的微调:让模型更贴近你的业务需求

大语言模型的微调&#xff1a;让模型更贴近你的业务需求 随着大语言模型&#xff08;LLM, Large Language Model&#xff09;如 GPT-4、BERT 和 T5 等的广泛应用&#xff0c;模型的微调&#xff08;Fine-tuning&#xff09;技术成为实现领域专属任务的重要手段。通过微调&…