柚见第十二期(随机匹配)

随机匹配

目的
为了帮大家更快地发现和自己兴趣相同的朋友
问题

匹配 1 个还是匹配多个?

答:匹配多个,并且按照匹配的相似度从高到低排序

怎么匹配?(根据什么匹配)

答:标签 tags
还可以根据 user_team 匹配加入相同队伍的用户
本质:找到有相似标签的用户
举例:
用户 A:[Java, 大一, 男]
用户 B:[Java, 大二, 男]
用户 C:[Python, 大二, 女]
用户 D:[Java, 大一, 女]

1. 怎么匹配
  1. 找到有共同标签最多的用户(TopN)

  2. 共同标签越多,分数越高,越排在前面

  3. 如果没有匹配的用户,随机推荐几个(降级方案)

2. 怎么对所有用户匹配,取 TOP

直接取出所有用户,依次和当前用户计算分数,取 TOP N

优化方法:

  1. 切忌不要在数据量大的时候循环输出日志(取消掉日志后 20 秒)
  2. Map 存了所有的分数信息,占用内存解决:
    维护一个固定长度的有序集合(sortedSet),只保留分数最高的几个用户(时间换空间)
    e.g : 【3, 4, 5, 6, 7】取 TOP 5,id 为 1 的用户就不用放进去了
  3. 细节:剔除自己 √
  4. 尽量只查需要的数据:
    a. 过滤掉标签为空的用户 √
    b. 根据部分标签取用户(前提是能区分出来哪个标签比较重要)
    c. 只查需要的数据(比如 id 和 tags) √(7.0s)
  5. 提前查?(定时任务)
  6. 提前把所有用户给缓存(不适用于经常更新的数据)
  7. 提前运算出来结果,缓存(针对一些重点用户,提前缓存)

大数据推荐

比如说有几亿个商品,难道要查出来所有的商品?
难道要对所有的数据计算一遍相似度?

检索 => 召回 => 粗排 => 精排 => 重排序等等

检索:尽可能多地查符合要求的数据(比如按记录查)
召回:查询可能要用到的数据(不做运算)
粗排:粗略排序,简单地运算(运算相对轻量)
精排:精细排序,确定固定排位

分表学习建议

  1. mycat框架
  2. sharding sphere 框架
  3. 一致性hash

随机匹配实现

编辑距离算法:

https://blog.csdn.net/DBC_121/article/details/104198838
最小编辑距离:字符串 str1 通过最少多少次增删改字符的操作可以变成字符串str2

! 没学过,不要紧,直接当成黑盒导入使用即可

余弦相似度算法:

https://blog.csdn.net/m0_55613022/article/details/125683937(如果需要带权重计算,比如学什么方向最重要,性别相对次要)

后端

引入工具类

新建工具类
cv 代码过来

在这里插入图片描述

简单测试一下

在这里插入图片描述

之前都是传入字符串,而实际需要比较的是两组字符数组

在这里插入图片描述

测试一下,是可以的

在这里插入图片描述

取出所有用户,依次和当前用户计算分数

bug : 笑死,为什么这里打印出来和数据库不一样

在这里插入图片描述

解决

使用这段代码成功

for (int i = 0; i <userList.size(); i++) {  
User user = userList.get(i);  
String userTags = user.getTags();  
//无标签的  
if (StringUtils.isBlank(userTags)){  
continue;  
}  
List<String> userTagList = gson.fromJson(userTags, new TypeToken<List<String>>() {  
}.getType());  
//计算分数  
int distance = AlgorithmUtils.minDistance(tagList, userTagList);  
indexDistanceMap.put(i,distance);  
}

使用这段代码失败
明明一样

for (int i = 0; i < userList.size(); i++) {  
User user=userList.get(i);  
String userTags=user.getTags();  
//判断用户是否有标签列表  
if(StringUtils.isBlank(userTags))  
{  
continue;  
}  
//将tags字符串转换为List  
List<String> userTagList=gson.fromJson(tags,new TypeToken<List<String>>(){  
}.getType());  
//计算分数(分数越低,相似度越高)  
int distance=AlgorithmUtils.minDistance(tagList,userTagList);  
indexDistanceMap.put(i,distance);  
}

在这里插入图片描述

完整代码

public List<User> matchUsers(int num, User loginUser) {  QueryWrapper<User> queryWrapper = new QueryWrapper<>();  
queryWrapper.isNotNull("tags");  
queryWrapper.select("id","tags");  
//1.查询所有用户  
List<User> userList=this.list(queryWrapper);  
//2.获取当前登录用户的标签  
//todo 前端传来可能是多个标签,这里是以字符串形式传递的吗?????  
String tags=loginUser.getTags();  
Gson gson=new Gson();  
//将字符串转换为List  
List<String> tagList=gson.fromJson(tags,new TypeToken<List<String>>(){  }.getType());  
System.out.println("当前登录用户的tagList : "+tagList);  
//用户列表的下标:相似度  
List<Pair<User,Integer>> list=new ArrayList<>();  
//3.遍历用户列表,获得相似度分数  
for (int i = 0; i < userList.size(); i++) {  
User user=userList.get(i);  
String userTags=user.getTags();  
//判断无标签或者当前user是登录用户  
if(StringUtils.isBlank(userTags) || loginUser.getId().equals(user.getId()))  
{  
continue;  
}  
//将tags字符串转换为List  
List<String> userTagList=gson.fromJson(userTags,new TypeToken<List<String>>(){  
}.getType());  
//计算分数(分数越低,相似度越高)  
int distance=AlgorithmUtils.minDistance(tagList,userTagList);  
list.add(new Pair<>(user,distance));  
}  
//4.按照编辑距离由小到大排序  
List<Pair<User, Integer>> topUserPairList = list.stream()  
.sorted((a, b) ->(int) (a.getValue() - b.getValue()))  
.limit(num)  
.collect(Collectors.toList());  
//有顺序的userID列表  
List<Integer> userListVo = topUserPairList.stream().map(pari -> pari.getKey().getId()).collect(Collectors.toList());  //根据id查询user完整信息  
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();  
userQueryWrapper.in("id",userListVo);  Map<Integer, List<User>> userIdUserListMap = this.list(userQueryWrapper)  
.stream()  
.map(user -> getSafetyUser(user))  
.collect(Collectors.groupingBy(User::getId));  // 因为上面查询打乱了顺序,这里根据上面有序的userID列表赋值  
List<User> finalUserList = new ArrayList<>();  
for (Integer userId : userListVo){  
finalUserList.add(userIdUserListMap.get(userId).get(0));  
}  
return finalUserList;  
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/749124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享一下自己总结的7万多字java面试笔记和一些面试视频,简历啥的,已大厂上岸

分享一下自己总结的7万多字java面试笔记和一些面试视频&#xff0c;简历啥的&#xff0c;已大厂上岸 自己总结的面试简历资料&#xff1a;https://pan.quark.cn/s/8b602fe53b58 文章目录 SSMspringspring 的优点&#xff1f;IoC和AOP的理解**Bean 的生命周期****列举一些重要…

一命通关差分

本章节是前缀和的延申 一命通关前缀和-CSDN博客https://blog.csdn.net/qq_74260823/article/details/136530291?spm1001.2014.3001.5501 一命通关前缀和 公交车 引入 还是利用我们在前缀和中所采用的例子——公交车。 有一辆公交车&#xff0c;一共上下了N批乘客&#xff1a…

【Vue3】源码解析-Runtime

文章目录 系列文章packages/runtime-dom/src/index.ts初始化创建renderermount \src\runtime-core\component.jsh.tspackages/runtime-core/src/renderer.ts挂载及卸载DOM节点render packages/runtime-dom/src/nodeOps.tspackages/runtime-core/src/apiCreateApp.ts创建appmoun…

全国农产品价格分析预测可视化系统设计与实现

全国农产品价格分析预测可视化系统设计与实现 【摘要】在当今信息化社会&#xff0c;数据的可视化已成为决策和分析的重要工具。尤其是在农业领域&#xff0c;了解和预测农产品价格趋势对于农民、政府和相关企业都至关重要。为了满足这一需求&#xff0c;设计并实现了全国农产…

RabbitMQ 面试题及答案整理,最新面试题

RabbitMQ的核心组件有哪些&#xff1f; RabbitMQ的核心组件包括&#xff1a; 1、生产者&#xff08;Producer&#xff09;&#xff1a; 生产者是发送消息到RabbitMQ的应用程序。 2、消费者&#xff08;Consumer&#xff09;&#xff1a; 消费者是接收RabbitMQ消息的应用程序…

哥斯拉流量webshell分析-->ASP/PHP

哥斯拉流量webshell分析 哥斯拉是继菜刀、蚁剑、冰蝎之后的又一个webshell利器&#xff0c;这里就不过多介绍了。 哥斯拉GitHub地址&#xff1a;https://github.com/BeichenDream/Godzilla 很多一线师傅不太了解其中的加解密手法&#xff0c;无法进行解密&#xff0c;这篇文章…

Web3社交项目UXLINK零撸教程

简介&#xff1a;UXLINK是Web3行业中首个主打双向、熟人社交关系的产品&#xff0c;与其他社交基础设施类项目相比&#xff0c;类似Twitter Vs Facebook、微博 Vs 微信的社交结构区别。UXLINK的愿景&#xff1a;1、社交中心&#xff1a;成为最大的社交平台&#xff0c;专注于真…

goctl-swagger 生成json接口文件

参考&#xff1a; GitHub - dyntrait/goctl-swagger: 通过 api 文件生成 swagger 文档 GitHub - Bluettipower/goctl-swagger 一:编译 执行go install 前一般需要设置环境&#xff0c;不然资源经常会下载不下载 go env -w GOPROXYhttps://goproxy.cn,direct 执行完 go in…

IO流(主要是记住四大类InputStream,OutputStream、Reader和Writer,其他都是他们的子类)

IO流 1、文件 &#xff08;1&#xff09;文件概念 文件就是保存数据的地方。例如word文档&#xff0c;txt文件&#xff0c;execl文件等等。 &#xff08;2&#xff09;文件流 文件在程序中是以流的形式来操作的。 流&#xff1a;数据在数据源&#xff08;文件&#xff09;…

【Python】Python中的正则表达式

Python中的正则表达式 1.re模块使用入门 1.1 re.match 函数 函数定义&#xff1a; re.match 尝试从字符串的起始位置匹配一个模式&#xff0c;如果不是起始位置匹配成功的话&#xff0c;match() 就返回 none。 函数语法&#xff1a; re.match(pattern, string, flags0) …

二叉树【Java】

二叉树遍历 前序遍历 中序遍历 后续遍历 代码 前 中 后序遍历 package Trww;public class TreeTraversal {/*12 34 5 6*/public static void main(String[] args) {TreeNode tree new TreeNode(new TreeNode(new TreeNode(4),2,null),1,new TreeNode(new TreeNode(5),3,n…

maven私服搭建详细教程

1、为什么需要私服 如果在公司中多个项目模块中的的公共类用的都是一样的&#xff0c;那么不可能将这些一样的代码写两遍。所以将其中一个项目中的代码打包成私服&#xff0c;然后在另外一个模块中去进行引用。 除此之外&#xff0c;如果大公司中开发人员较多&#xff0c;大家同…

《ElementPlus 与 ElementUI 差异集合》icon 图标使用(包含:el-button,el-input和el-dropdown 差异对比)

安装 注意 ElementPlus 的 Icon 图标 要额外安装插件 element-plus/icons-vue. npm install element-plus/icons-vue注册 全局注册 定义一个文件 element-icon.js &#xff0c;注意代码第 6 行。加上了前缀 ElIcon &#xff0c;避免组件命名重复&#xff0c;且易于理解为 e…

TinTin Web3 动态精选:以太坊坎昆升级利好 Layer2,比特币减半进入倒计时

TinTin 快讯由 TinTinLand 开发者技术社区打造&#xff0c;旨在为开发者提供最新的 Web3 新闻、市场时讯和技术更新。TinTin 快讯将以周为单位&#xff0c; 汇集当周内的行业热点并以快讯的形式排列成文。掌握一手的技术资讯和市场动态&#xff0c;将有助于 TinTinLand 社区的开…

【每日力扣】235. 二叉搜索树的最近公共祖先与39. 组合总和问题描述

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害。 235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义…

硬件工程师入门基础知识(零)心法篇

硬件工程师入门基础知识(零)心法篇 1.为什么要当硬件工程师?2.什么是硬件工程师?3.怎么成为合格的硬件工程师?4.优秀的硬件工程师需要具备什么技能和品质?5.硬件工程师的成长路径?6.硬件工程师还有哪些职业可能?1.为什么要当硬件工程师? 很多快要毕业或者刚毕业的同学…

【2024年5月备考新增】《软考真题分章练习 - 5 项目进度管理(高项)》

1、( ) is a technique for estimating the duration or cost of an activity or a project using historical data from a similar activity or project. A.Analogous estimating B. parametric estimating C.Three-Point estimating D. Bottom estimating 2、下图中(单位:…

如何本地搭建hMailServer邮件服务

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

免密ssh密钥登录Linux该如何设置

我们在使用ssh客户端远程连接Linux服务器时&#xff0c;为了考虑安全方面的因素&#xff0c;通常使用密钥的方式来登录。密钥分为公钥和私钥&#xff0c;这两把密钥可以互为加解密。公钥是公开的&#xff0c;私钥是由个人自己持有&#xff0c;并且必须妥善保管和注意保密。 Li…

《圣斗士星矢》AI制作真人大电影宣传片

《圣斗士星矢》AI制作真人大电影宣传片 The ancient gods awaken, a battle of light and shadow unfolds.古神觉醒&#xff0c;光明与黑暗之战一触即发。 Heroes stand, facing the abyss of evil.英雄挺立&#xff0c;直面邪恶深渊。 The stars align, the chosen ones ris…