es修改排序_ElasticSearch 评分排序
背景
通过脚本改变评分
背景
近期有一个需求,需要对优惠券可用商品列表加个排序,只针对面值类的券不包括折扣券。
需求是这样的,假设有一张面值券 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 方式。
脚本默认是 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_mode ,boost_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只是一个简单的场景。
作者:王清培 (沪江集团资深架构师)
es修改排序_ElasticSearch 评分排序相关推荐
- ElasticSearch源码解析(五):排序(评分公式)
ElasticSearch源码解析(五):排序(评分公式) 转载自:http://blog.csdn.net/molong1208/article/details/50623948 一.目的 一个 ...
- sql多字段求和降序排序_elasticsearch基础笔记11-搜索排序
1.默认排序 ES是按照查询和文档的相关度进行排序的,默认是降序排列,也就是说,我们之前的查询, 可以认为是下面这样子的,. 当然,我们也可以换一个字段来进行排序,那么,就不用评分了. 全文搜索也类似 ...
- Elasticsearch中的评分排序--Function score query
文章目录 1. 背景 2. 数据构建 3. function score使用 3.1 function score示例 3.2 参数说明 1. 背景 实际开发中,使用elasticsearch做搜索时 ...
- 对后台返回的数据进行评分排序、时间排序!
导读:对后台返回的数据进行评分排序,时间排序,可以倒序,可以正序. 按照评分排序 正序 qualityScoreSort(){this.tableData0.sort((a, b) => {re ...
- python爬取豆瓣读书_用python+selenium抓取豆瓣读书中最受关注图书并按照评分排序...
抓取豆瓣读书中的(http://book.douban.com/)最受关注图书,按照评分排序,并保存至txt文件中,需要抓取书籍的名称,作者,评分,体裁和一句话评论 方法一:#coding=utf-8 ...
- Aimp3的播放列表 按评分排序 落雨
如图,添加评分选项,并保存,就可以在下图的选项里找到此选项,并按评分排序 效果图如下:还可以倒置,迅速使评分高的音乐排在播放列表的前面位置!! 转自百度知道: http://zhidao.baidu. ...
- 用python+selenium抓取豆瓣电影中的正在热映前12部电影并按评分排序
抓取豆瓣电影(http://movie.douban.com/nowplaying/chengdu/)中的正在热映前12部电影,并按照评分排序,保存至txt文件 1 #coding=utf-8 2 f ...
- 数组查找、赋值、复制、反转及修改,三种常用排序算法
1.线性查找:通过遍历的方式,一个一个的数据进行比较.查找(具有普遍适用性).. public class ArrTest001{//线性查找public static void main(Strin ...
- 学生管理系统 结构体+链表(登录,注册,查询,修改,删除,排序,求平均)
学生管理系统-使用链表(优化) # 登录,注册,查询,修改,删除,排序,求平均 转载--网络资源 #include<stdio.h> #include<string.h> #i ...
最新文章
- Java 程序员薪资这么高,取决于什么?
- 字符串操作--宽窄字符转换
- JavaEE XML的读写(利用JDom对XML文件进行读写)
- c#图片base64去转义字符_C#实现字符串与图片的Base64编码转换操作示例|chu
- Python3中的hasattr()
- 物联网智慧城市为降低城市能源消耗做出贡献
- linux php c 扩展,linux php添加扩展库
- (Python第七天)实例二玩转函数
- 控制台怎么查看错误的详细信息_js错误处理,quot;try..catchquot;
- SLAM综述之ORB-SLAM3论文精读: An Accurate Open-Source Library for Visual, Visual-Inertial and Multi-Map SLAM
- JSP学习——Eclipse自定义JSP模板(修改默认JSP文件)
- 数字日期格式转换yyyymmdd_js时间转换,能够把时间转换成yyyymmdd格式或yyyymm格式...
- 阿里巴巴分布式服务框架HSF
- Android应用安全检测项目
- c语言常量(c语言常量定义规则)
- 3.4 智能手表整体结构设计总结
- Windows 7 SP1相关资源下载
- win10虚拟机搭建群晖nas碰到的一些问题
- SkyEye硬件模拟平台
- 《李航 统计学习方法》学习笔记——第八章提升方法