ElasticSearch 评分排序

2023-10-31

  • 背景
  • 通过脚本改变评分

背景

近期有一个需求,需要对优惠券可用商品列表加个排序,只针对面值类的券不包括折扣券。

需求是这样的,假设有一张面值券 50 块钱,可用商品列表 A 100、B 40、C 10,当用户查询当前券可用商品列表的时候优先将卡券可以直接抵扣且不需要用户在额外支付的商品排在前面。

C 10
B 40
A 100

其实排序有很多侧重,比如:

1.根据用户利益最大化原则,排序列表应该是 B、C、A
2.根据用户购买习惯,有可能是 A、B、C
3.根据运营策略、第三方利益等有可能是C、B、A

这里暂且先不扩展如何对商品列表进行智能排序,如果需要完整的个性化商品推荐,涉及很多东西,后面有经验在拿来分享。

我们就这个简单的 case,一开始最直接的想法就是加个排序列,建索引的时候将排序值计算好直接写入。后来分析了下原来索引(index) 结构不是这种笛卡尔积的排列,所以在短时间内很难立马上线,需要新建 index 结构。

后来通过讨论用影响评分的方法来解决,可以节省时间快速上线。

通过脚本改变评分

ES query DSL 支持很多种类型的查询,结果的排序如果没有特殊声明 sort field 则是根据es打分(score)来排序的,score 分值越高排序越靠前。

ES score 计算比较复杂,涉及到 TF(词频)/IDF(逆向文档频率)罕见词匹配文档长度权重 boost 向量空间模型 等,不过 ES 提供了几种封装好的评分插件供使用。

function_score 查询来让我们根据业务场景改变文档评分方法,根据业务场景我们需要完全控制 score 生成的逻辑,所以我们选择 script_score 方式。

script_score
如果需求超出以上范围时,用自定义脚本可以完全控制评分计算,实现所需逻辑。
(参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/function-score-query.html

脚本默认是 groovy,当然也可以根据需要使用其他脚本语言,我们来看下实现。

script.inline: on
script.enfine.groovy.inline.aggs: on
script.indexed: on
script.file: on

首先在 es.yml 配置中打开脚本支持相关选项。

{
    "query": {
        "function_score": {
            "query": {
                "bool": {
                    "should": [
                        {
                            "match": {
                                "productName": "英语"
                            }
                        }
                    ]
                }
            },
            "score_mode": "first",
            "script_score": {
                "lang": "groovy",
                "params": {
                    "couponPrice": 100
                },
                "script": "def deduct = couponPrice - doc['unitCost'].value.toFloat(); if (deduct > 0) {return 10000 + deduct;}else if(deduct==0 || (deduct<1 && deduct>0)){return 20000;}else{return  doc['unitCost'].value.toFloat()-couponPrice;}"
            },
            "boost_mode": "replace"
        }
    },
    "from": 0,
    "size": 100
}

查询条件可以任意,关键是 script_score 对象,script 是需要 ES 脚本引擎执行的脚本代码。

一个比较重要的选项 boost_modeboost_mode 是控制整个 document 的评分方式,这里我们选择替代(replace)默认计算好的评分。

这里面的排序有一个小技巧,如何将负数排序在前面,正数排序在后面,还有抵扣后是0的处理。

def deduct = couponPrice - doc['unitCost'].value.toFloat(); 
if (deduct > 0) {
    return 10000 + deduct; 
}else if(deduct==0 || (deduct<1 && deduct>0)){
    return 20000; 
}else{
    return  doc['unitCost'].value.toFloat()-couponPrice;
}

通过 couponPrice 变量表示优惠券面值金额,如果当前商品抵扣完是负数说明需要排序在前面,那么如何和抵扣完正数分开尼,这里可以取一个稍微大点的值加上抵扣后的负值,这样把负值转换成正数自然就排序在前面。

抵扣后等于0的或者小于1大于0的值也是可以优先安排在前面,当然这里还是不够灵活的,最好的方式是根据当前面值、商品价格动态计算才准确。

最后就是抵扣完需要用户在额外支付的排在最后面,直接取需要额外支付的金额数值作为排序。

通过 ES 评分我们能做很多事情,这个case只是一个简单的场景。

作者:王清培 (沪江集团资深架构师)

转载于:https://www.cnblogs.com/wangiqngpei557/p/10423875.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ElasticSearch 评分排序 的相关文章

  • 统计学习方法——概述

    统计学习方法之概述 1 统计学习的特点 1 统计学习以计算机及网络为平台 是建立在计算机及网络上的 2 统计学习以数据为研究对象 是数据驱动的学科 3 统计学习的目的是对数据进行预测与分析 4 统计学习以方法为中心 统计学习方法构建模型井应
  • windows10企业版开启RDP多用户同时登录

    1 系统属性 开启远程桌面 添加远程桌面登录用户 2 快捷键win R 输入 gpedit msc 打开本地组策略编辑器 选择 管理模板 gt Windows组件 gt 远程桌面服务 gt 远程桌面会话主机 gt 连接 配置 限制连接的数量
  • 夯实网络安全基石,筑牢网络安全防线

    没有网络安全就没有国家安全 这句话我们常常能在各种新闻里看见 安全是发展的前提 发展是安全的保障 共同推进安全和发展 Z强调 要坚持依法治网 依法办网 依法上网 今年的国家网络安全宣传周在9月11日至17日全国范围内开展 今年的网安周以 网
  • 电脑重装系统后需要更新哪些驱动

    在电脑重装系统后 由于系统的重置 您需要重新安装和更新一些关键的驱动程序 以确保硬件设备正常工作和性能最佳化 以下是在电脑重装系统后需要更新的一些常见驱动程序 工具 原料 系统版本 win10系统 品牌型号 戴尔 XPS13 9350 37

随机推荐

  • H5新增标签 css图标库 web 前端 字体 问题

    目录 css图标库 web前端字体 CSS Hint H5新增标签 1
  • OpenCV学习(2)——图像的数据格式BGR

    OpenCV学习 2 图像的BGR格式解读 1 opencv读取的图片数据格式 2 BGR含义 1 opencv读取的图片数据格式 opencv读取的图片数据格式为numpy的nparray格式 一张二维图片是由像素点构成 如下图所示 其中
  • Mysql:增删改查基础语句

    mysql基础入门语句 增 INSERT INTO 表名 字段1 2 3 VALUES 值1 2 3 删 DELETE FROM 表明 WHERE 删除条件 不提供更新条件 则删除所有 改 UPDATE 表名 SET 字段1 新值 字段2
  • JavaScript学习 -- ajax方法的POST请求

    在Web开发中 通过POST请求将数据发送给服务器是一种常见的方式 使用jQuery可以轻松地发送POST请求 这需要使用jQuery的ajax 方法 本文将介绍jQuery如何使用POST请求发送数据 并提供一个实际的例子 使用 ajax
  • rcp命令

    http www cnblogs com peida archive 2013 03 14 2958685 html rcp代表 remote file copy 远程文件拷贝 该命令用于在计算机之间拷贝文件 rcp命令有两种格式 第一种格
  • Py_Finalize引发的异常

    Py Finalize引发如下异常 0x00007FFFE5A28D10 python38 dll 处 位于 MTFform exe 中 引发的异常 0xC0000005 执行位置 0x00007FFFE5A28D10 时发生访问冲突 解决
  • 项目系列之登录管理

    登录管理是现代计算机系统中关键的组成部分之一 那么本篇博客我们来简单了解一下登录的流程与前后端干了啥事 一 登录流程 用户打开登录页面 用户访问应用程序或网站的登录页面 此页面通常包含用户名 邮箱输入字段和密码输入字段 以及登录按钮 用户输
  • 2、模板方法

    文章目录 概念 demo 概念 父类定义抽象 的 template method 并由别的方法调用 子类实现具体的 template method 和观察者类似 回调函数 钩子函数 都是此模式的应用 观察者一般是多个 方法由被观察者调用 模
  • redhat6.4 下安装oracle 11g详细完整的步骤

    一 虚拟机安装操作系统 Redhat 6 4 注意 linux下安装oracle 11 如果是redhat系统 选择redhat6版本的 因为redhat7版本里面少一个安装数据库用到的包compat libstdc 33 没有这个包 安装
  • flutter自定义广告Banner

    Flutter 1 0 is out Tuesday December 4 2018 Banner是手机应用最常见的需求之一 https pub dartlang org flutter中搜索Banner找到两个开源库 引入项目后 分别存在
  • 项目应用:使用自定义注解完成对controller的aop控制

    在项目进行过程中 需要使用aop对api传入或者传出数据进行日志记录 考虑实际应用 放弃了使用拦截器 转而使用aop的前置通知和返回通知中加入日志记录操作 在spring中 controller会被JDK自动代理 当使用自定义标签时cont
  • R语言的基本数据类型:数值,字符串,逻辑

    R语言的基本数据类型 数值 双整型 储存普通数值型数据 可正可负 可大可小 可含小数可不含 R中输入的任何一个数值都默认以双整型存储 可以使用typeof 函数来查看对象类型 在数据科学里 它更常被称为数值型 整型 只能用来储存正数 在R中
  • 前端面试题之——兼容篇

    兼容性面试题 一 html 部分 1 H5 新标签在 IE9 以下的浏览器识别 html5shiv js 下载地址 2 ul 标签内外边距问题 ul 标签在 IE6 IE7 中 有个默认的外边距 但是在 IE8 以上及其他浏览器中 有个默认
  • websphere6.x 调用集群EJB的Context.PROVIDER_URL写法

    import java util Hashtable import javax naming Context import javax naming InitialContext Hashtable env new Hashtable en
  • caffe源码解析 — net.cpp

    Net类是Solve类的一个成员 在net cpp中定义了对Net的所有操作 其中包括 Init GetLearningRateAndWeightDecay ForwardPrefilled Backward ShareTrainedLay
  • 计算机数值转换教案,计算机数值方法教案.doc

    第O章 绪论 一 教学设计 1 教学内容 数值计算方法这门课程的形成背景及主要研究内容 研究方法 主要特点 算法的有关概念及要求 误差的来源 意义 及其有关概念 数值计算中应注意的一些问题 2 重点难点 算法设计及其表达法 误差的基本概念
  • 数据结构——快速排序

    1 原理及代码实现 快速排序 快速排序也是一种分治的排序算法 快速排序和归并排序是互补的 归并排序将数组分成两个子数组分别排序 并将有序的子数组归并以将整个数组排序 会需要一个额外的数组 而快速排序的排序方式是当两个子数组都有序时 整个数组
  • @Async注解线程池

    在启动类上添加 EnableAsync配合该注解使用 自定义线程池方法 implements AsyncConfigurer extends AsyncSupportConfigurer Bean 注入线程池 public interfac
  • Shell中表示数字跨度的几种方式

    在Shell脚本中 如果要输出数字为0 20中3的倍数 可以使用下面三种方式来完成 方式一 i 0 i lt 20 i 3 for i 0 i lt 20 i 3 do echo i done 方式二 0 20 3 for i in 0 2
  • ElasticSearch 评分排序

    背景 通过脚本改变评分 背景 近期有一个需求 需要对优惠券可用商品列表加个排序 只针对面值类的券不包括折扣券 需求是这样的 假设有一张面值券 50 块钱 可用商品列表 A 100 B 40 C 10 当用户查询当前券可用商品列表的时候优先将