当前位置: 首页 > article >正文

基于Elasticsearch的个性化内容推荐技术实践

近期开发了一款新的app,并深度参与的全流程的构建及开发,在开发首页内容推荐的时候,写了一套通过ES实现的推荐算法,小有所得,写此博客记录一下。

一、Elasticsearch在推荐系统中的核心作用

1.1 实时索引与检索

Elasticsearch采用倒排索引技术,能够快速索引海量内容数据,并支持毫秒级检索。在推荐系统中,实时性至关重要,用户的行为数据和内容数据需要实时更新和检索。

SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder().index(SearchCommonConstant.CONTENT_INDEX_NAME).from(current).size(limit);

通过合理的索引设计,Elasticsearch可以轻松处理千万级甚至亿级的数据量,为推荐系统提供坚实的数据基础。

1.2 灵活的查询构建

Elasticsearch支持多种查询方式,包括布尔查询、范围查询、模糊查询等。在推荐系统中,我们可以通过组合查询构建复杂的推荐逻辑。

//该处进行复杂查询的query语句构建
Query query = recommendContentQueryBuilder(params).build();

布尔查询用于组合多个条件,范围查询用于时间窗口的筛选,模糊查询用于处理用户输入的不确定性。这些查询方式为推荐算法提供了强大的表达能力。

1.3 脚本评分功能

脚本评分是Elasticsearch中实现个性化推荐的核心技术。通过Painless脚本,我们可以在查询时动态计算每个文档的评分值,从而实现基于多种因素的个性化排序。(因涉及公司业务保密数据,这里不做具体代码展示)

// RecommendScript.HOME_CES_SCRIPT是你需要执行的ES推荐算法脚本
InlineScript inlineScript = new InlineScript.Builder().source(RecommendScript.HOME_CES_SCRIPT).params(scriptParams).build();

脚本评分的实现逻辑包括以下几个关键步骤:
参数传递:通过params动态传递算法参数,如时间窗口、权重值等。
文档字段访问:在脚本中访问文档的字段值,如发布时间、互动数据等。
权重计算:根据业务规则动态调整权重,如时间衰减、标签匹配等。

二、推荐算法的实现框架

2.1 动态脚本评分机制

动态脚本评分机制是推荐算法的核心,它允许我们在查询时动态计算文档的评分值。这种机制的优势在于灵活性和实时性,可以根据用户行为和内容特征实时调整推荐逻辑。

Script script = new Script.Builder().inline(inlineScript).build();

在脚本中,我们可以通过访问文档字段和传递参数,实现复杂的评分逻辑。例如,根据内容的发布时间、互动数据、用户兴趣标签等因素计算最终评分。

2.2 函数查询(Function Score Query)

函数查询是Elasticsearch中一种强大的查询方式,用于结合多种评分函数对文档进行加权。我们通过FunctionScoreQuery构建复合查询,将脚本评分与其他查询条件结合。

//下面是es执行的函数语句构建过程
FunctionScore functionScore = new FunctionScore.Builder().scriptScore(s -> s.script(script)).build();FunctionScoreQuery functionScoreQuery = new FunctionScoreQuery.Builder().query(query).functions(Collections.singletonList(functionScore)).scoreMode(FunctionScoreMode.Sum).boostMode(FunctionBoostMode.Replace).build();

函数查询的主要特点包括:
多函数组合:支持多种评分函数的组合,如权重函数、衰减函数等。
灵活的评分模式:通过scoreMode和boostMode控制最终评分的计算方式。

2.3 动态参数传递

为了提高算法的灵活性,我们通过动态参数传递机制,将算法参数与脚本分离。这样可以在不修改脚本的情况下,灵活调整算法逻辑。

//以对象方式进行es脚本的变量赋值,方便动态调整算法权重
Map<String, JsonData> scriptParams = new HashMap<>();
scriptParams.put("hot50", JsonData.of(50));
scriptParams.put("pvCount", JsonData.of(100));
scriptParams.put("weightANew", JsonData.of(10.0));
scriptParams.put("weightAOld", JsonData.of(8));
scriptParams.put("weightBMatch", JsonData.of(5));

动态参数的主要作用包括:
时间窗口配置:通过参数控制时间衰减的窗口大小。
权重调整:动态调整不同因素的权重值。
用户兴趣匹配:传递用户兴趣标签,增强个性化推荐能力。

三、推荐算法的技术亮点

3.1 时间衰减模型

时间衰减是推荐系统中的重要机制,用于平衡内容的新鲜度与质量。我们通过脚本计算内容的发布时间与当前时间的差值,动态调整权重。

long now = new Date().getTime();
long publishTime = doc['publishTime'].value.toInstant().toEpochMilli();
long day90 = params.hot50 * 86400000L;
long day180 = params.hot100 * 86400000L;if (publishTime > (now - day90) && doc['pvCount'].value < pvThreshold) {weight_a = params.weightANew; // 新发布内容
} else if (publishTime <= (now - day180)) {weight_a = params.weightAOld; // 历史内容
}

时间衰减的主要作用包括:
新内容优先:对新发布的内容给予更高的权重。
历史内容保底:对优质历史内容保留一定的曝光机会。

3.2 用户喜好匹配

用户喜好内容是个性化推荐的重要依据。我们通过脚本动态匹配用户喜好与内容类型,增强推荐的相关性。

if (doc['industryCodes.keyword'].size() > 0 && params.userIndustryTags != null) {for (def code : params.userIndustryTags) {if (doc['industryCodes.keyword'].contains(code)) {weight_b = params.weightBMatch;break;}}
}

用户喜好匹配的主要作用包括:
精准推荐:根据用户喜好类型推荐相关内容。
动态调整:实时更新用户喜好,提升推荐的动态性。

3.3 互动数据加权

互动数据(如点赞、收藏、粉丝数)是衡量内容质量的重要指标。我们通过脚本动态计算互动数据的权重,增强推荐的客观性。

double praise = doc['praiseCount'].size() > 0 ? doc['praiseCount'].value : 0;
double collect = doc['collectionCount'].size() > 0 ? doc['collectionCount'].value : collect_weight;
double follow = doc['fansCount'].size() > 0 ? doc['fansCount'].value * follow_weight : 0;

互动数据加权的主要作用包括:
质量优先:对互动数据较高的内容给予更高的权重。
多维度评估:综合考虑多种互动指标,避免单一指标的偏差。

四、性能优化与扩展性

4.1 性能优化

为了确保推荐系统的高性能,我们采取了以下优化措施:
索引优化:合理设计索引结构,减少不必要的字段存储。例如,使用keyword类型存储标签字段,避免分析器的开销。
查询优化:通过布尔查询过滤无关内容,减少脚本评分的计算量。例如,先通过范围查询筛选出时间窗口内的内容,再进行脚本评分。
缓存机制:对高频查询结果进行缓存,减少重复计算。Elasticsearch内置的查询缓存和请求缓存可以显著提升性能。

4.2 扩展性设计

为了支持未来的业务扩展,我们在设计中注重以下几点:
参数化设计:通过动态参数传递机制,支持算法的灵活调整。例如,通过配置文件管理时间窗口和权重值,方便后续调整。
模块化实现:将推荐逻辑拆分为多个独立模块,便于后续扩展。例如,将时间衰减、用户喜好匹配、互动数据加权等逻辑分离为独立模块。
脚本分离:将算法逻辑与脚本分离,便于维护和更新。脚本存储在外部文件中,通过API动态加载,避免频繁更新代码。

五、总结

通过基于Elasticsearch的个性化内容推荐技术实践,我们成功构建了一个高效、灵活的推荐引擎。该引擎通过动态脚本评分、函数查询、时间衰减模型、用户喜好内容匹配等技术,实现了精准的个性化推荐。

相关文章:

基于Elasticsearch的个性化内容推荐技术实践

近期开发了一款新的app&#xff0c;并深度参与的全流程的构建及开发&#xff0c;在开发首页内容推荐的时候&#xff0c;写了一套通过ES实现的推荐算法&#xff0c;小有所得&#xff0c;写此博客记录一下。 一、Elasticsearch在推荐系统中的核心作用 1.1 实时索引与检索 Elast…...

el-radio-group 中 el-radio-button value未能绑定上数值数据

这样绑定到admin后不会随着admin的值显示 在value加上 : 后成功显示...

Python Cookbook-4.13 获取字典的一个子集

任务 你有一个巨大的字典&#xff0c;字典中的一些键属于一个特定的集合&#xff0c;而你想创建一个包含这个键集合及其对应值的新字典。 解决方案 如果你不想改动原字典: def sub_dict(somedict,somekeys,default None):return dict([(k, somedict.get(k,default)) for k…...

JSP(实验):带验证码的用户登录

[实验目的] 1&#xff0e;掌握应用request对象获取表单提交的数据。 2&#xff0e;掌握解决获取表单提交数据产生中文乱码的问题。 3&#xff0e;掌握使用response对象进行定时跳转功能。 4&#xff0e;掌握使用session对象完成登录和注销功能。 [实验要求] 设计带验证码…...

自然语言模型的演变与未来趋势:从规则到多模态智能的跨越

自然语言模型的演变与未来趋势&#xff1a;从规则到多模态智能的跨越 自然语言处理(NLP)作为人工智能领域最具挑战性的分支之一&#xff0c;在过去几十年经历了翻天覆地的变化。从最初基于规则的系统到如今拥有万亿参数的大型语言模型(LLMs)&#xff0c;这一技术革新不仅彻底改…...

集多功能为一体的软件,支持批量操作。

今天我给大家分享一个超实用的小工具&#xff0c;真的是太好用了&#xff01;这个软件是吾爱大神无知灰灰制作的&#xff0c;它能直接一键把webp格式的图片转换成png格式。 webp转为png 一键操作&#xff0c;支持压缩 其实&#xff0c;作者最近在工作中经常遇到webp格式的图片…...

linux压缩指令

今天我们来了解一下linux压缩指令,压缩是我们文件传输的一种重要手段,对此,我们是必须学习压缩指令的,那么话不多说,来看. 1.grep过滤查找&#xff0c;管道符&#xff0c;“&#xff5c;”&#xff0c;表示将前一个命令的处理结果输出传递给后面的命令处理。 基本语法&#x…...

C++细节知识for面试

1. linux上C程序可用的栈和堆大小分别是多少&#xff0c;为什么栈大小小于堆&#xff1f; 1. 栈&#xff08;Stack&#xff09;大小 栈默认为8MB&#xff0c;可修改。 为什么是这个大小&#xff1a; ​安全性&#xff1a;限制栈大小可防止无限递归或过深的函数调用导致内存…...

Appium中元素定位的注意点

应用场景 了解这些注意点可以以后在出错误的时候&#xff0c;更快速的定位问题原因。 示例 使用 find_element_by_xx 或 find_elements_by_xx 的方法&#xff0c;分别传入一个没有的“特征“会是什么结果呢? 核心代码 driver.find_element_by_id("xxx") drive…...

污水处理厂人员定位方案-UWB免布线高精度定位

1. 方案概述 本方案采用免布线UWB基站与北斗卫星定位融合技术&#xff0c;结合UWBGNSS双模定位工卡&#xff0c;实现污水处理厂室内外人员高精度定位&#xff08;亚米级&#xff09;。系统通过低功耗4G传输数据&#xff0c;支持实时位置监控、电子围栏、聚集预警、轨迹回放等功…...

蓝桥刷题note11(好数)

1&#xff0c;好数 一个整数如果按从低位到高位的顺序&#xff0c;奇数位 (个位、百位、万位 ⋯⋯ ) 上的数字是奇数&#xff0c;偶数位 (十位、千位、十万位 ⋯⋯ ) 上的数字是偶数&#xff0c;我们就称之为 “好数”。 给定一个正整数 NN&#xff0c;请计算从 1 到 NN 一共…...

Elasticsearch 高级

Elasticsearch 高级 建议阅读顺序&#xff1a; Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级&#xff08;本文&#xff09; 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构&#xff0c;比如一个…...

SQL Server 2022常见问题解答

以下是SQL Server 2022的常见问题解答,按主题分类整理: 一、安装与升级 SQL Server 2022的系统要求是什么? 支持的操作系统:Windows Server 2016及以上、Linux(Ubuntu 20.04/22.04, RHEL 8/9等)。内存:至少4GB(建议8GB+)。磁盘空间:6GB以上,具体取决于安装组件。如何…...

基于LLM的实时信息检索汇总分析系统

基于用户需求和技术发展趋势&#xff0c;设计基于LLM的实时信息检索汇总分析系统&#xff0c;方案如下&#xff1a; 一、系统架构设计 1. 分层多模态数据采集层 动态渲染适配引擎 采用混合爬虫技术&#xff1a; 静态页面&#xff1a;优化Scrapy框架&#xff0c;集成XPath模板库…...

C语言笔记数据结构(链表)

希望文章能对你有所帮助&#xff0c;有不足的地方请在评论区留言指正,一起交流学习! 目录 1.链表 1.1 链表概念和组成 1.2 链表的分类 1.3 顺序表和链表 2.单链表&#xff08;无头单向不循环链表&#xff09; 2.1 结点的创建 2.2 创建新的结点 2.3 单链表的打印 2.4 尾…...

Leetcode 两数相除

✅ LeetCode 29. 两数相除 — 思路总览 &#x1f9e9; 题目要求 给定两个整数 dividend 和 divisor&#xff0c;实现 整数除法&#xff0c;不能使用乘法 *、除法 / 和取余 % 运算符。 要求返回的结果应为 向零截断的整数商&#xff0c;即&#xff1a; 正数向下取整&#xf…...

C++ 初阶总复习 (16~30)

C 初阶总复习 &#xff08;16~30&#xff09; 目的16. 2009. volatile关键字的作用17. 2010.什么是多态 简单介绍下C的多态18. 2011. 什么是虚函数 介绍下C中虚函数的原理19. 2012 构造函数可以是虚函数嘛20. 2013.析构函数一定要是虚函数嘛&#xff1f;21. 2015. 什么是C中的虚…...

Koordinator-Metric查询

以CollectAllPodMetricsLast()举例,看看koordinator怎样使用tsdb进行查询。 CollectAllPodMetricsLast() GenerateQueryParamsLast()传入metric采集间隔2倍时间调用CollectAllPodMetrics()func CollectAllPodMetricsLast(statesInformer statesinformer.StatesInformer, metr…...

人工智能图像识别Scala介绍

Scala 一.Scala 简介 Scala即Scalable Language&#xff08;可伸缩的语言&#xff09;&#xff0c;Scala 语言是由 Martin Odersky 等人在 2003 年开发的&#xff0c;并于 2004 年首次发布。意味着这种语言设计上支持大规模软件开发&#xff0c;是一门多范式的编程语言。 Sc…...

PCL 点云多平面探测

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里实现了一种点云多平面探测的算法,该算法使用基于鲁棒统计的方法进行平面补丁检测。该算法具体过程:首先将点云细分为更小的块(使用二分法),然后尝试为每个点云块匹配一个平面。如果平面通过了鲁棒平面性测试…...

npm i 出现的网络问题

npm i 出现的网络问题 解决方案&#xff1a; npm config list 查看.npmrc文件中是否配置了proxy删除.npmrc文件中的proxy&#xff0c;保存。重新执行npm i命令。 顺便说说解决这个问题的心里路程 每次安装vue的环境的时候&#xff0c;经常遇到npm安装一些插件或者是依赖的时…...

C++中使用CopyFromRecordset将记录集拷贝到excel中时,如果记录集为0个,函数崩溃,是什么原因

文章目录 原因分析解决方案1. 检查记录集是否为空2. 安全调用COM方法3.进行异常捕获4. 替代方案&#xff1a;手动处理空数据 总结 在C中使用CopyFromRecordset将空记录集&#xff08;0条记录&#xff09;复制到Excel时崩溃的原因及解决方法如下&#xff1a; 原因分析 空记录集…...

代码随想录算法训练营--打卡day3

复习&#xff1a;标注感叹号的需要在电脑上重新做几遍 一.两两交换链表中的节点&#xff01;&#xff01; 1.题目链接 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 2.思路 画图 3.代码 class Solution {public ListNode swapPairs(ListNode head) …...

c#的.Net Framework 的console 项目找不到System.Window.Forms 引用

首先确保是建立的.Net Framework 的console 项目,然后天健reference 应用找不到System.Windows.Forms 引用 打开对应的csproj 文件 在第一个PropertyGroup下添加 <UseWindowsForms>true</UseWindowsForms> 然后在第一个ItemGroup 下添加 <Reference Incl…...

蓝桥杯嵌入式学习笔记

用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历 工具环境准备cubemx配置外部高速时钟使能设置串口时钟配置项目配置 keil配置烧录方式注意代码规范头文件配置 模块ledcubemx配置keil代码实现点亮一只灯实现具体操作的灯&#xff0c;以及点亮还是熄灭 按键cubemx配置k…...

zookeeper详细介绍以及使用

Zookeeper 是一个开源的分布式协调服务&#xff0c;提供了一个高效的分布式数据一致性解决方案。它的主要作用是维护集群中各个节点之间的状态信息&#xff0c;协调节点之间的工作&#xff0c;并处理节点宕机等故障情况。Zookeeper 的核心功能包括数据发布/订阅、分布式锁、集群…...

Blender多摄像机怎么指定相机渲染图像

如题目所说&#xff0c;当blender的场景里面有摄像机的时候&#xff0c;按F12可以预览渲染结果&#xff0c;但是当有多个摄像机的时候就不知道使用哪个进行渲染了。 之前在网上没有找到方法&#xff0c;就用笨方法&#xff0c;把所有的摄像机删除&#xff0c;然后设置自己需要…...

Redis场景问题1:缓存穿透

Redis 缓存穿透是指在缓存系统&#xff08;如 Redis&#xff09;中&#xff0c;当客户端请求的数据既不在缓存中&#xff0c;也不在数据库中时&#xff0c;每次请求都会直接穿透缓存访问数据库&#xff0c;从而给数据库带来巨大压力&#xff0c;甚至可能导致数据库崩溃。下面为…...

CSS 如何设置父元素的透明度而不影响子元素的透明度

CSS 如何设置父元素的透明度而不影响子元素的透明度 在 CSS 中&#xff0c;设置父元素的透明度&#xff08;如通过 opacity 属性&#xff09;会影响所有子元素的透明度&#xff0c;因为 opacity 是作用于整个元素及其内容的。如果想让父元素透明但不影响子元素的透明度&#x…...

Java的string默认值

在Java中&#xff0c;String类型的默认值取决于其定义和实例化的方式。 以下是关于String默认值的详细说明 未实例化的String变量‌ 如果定义一个String变量但未对其进行实例化&#xff08;即未使用new关键字或直接赋值&#xff09;&#xff0c;其默认值为:ml-search[null]。这…...