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

随机匹配

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

匹配 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.hqwc.cn/news/543468.html

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

相关文章

经典机器学习模型(一)感知机模型

经典机器学习模型(一)感知机模型 感知机可以说是一个相当重要的机器学习基础模型&#xff0c;是神经网络和支持向量机的基础。 感知机是一个二分类的线性分类模型&#xff0c;之所以说是线性&#xff0c;是因为它的模型是线性形式的。 从《统计学习方法》中&#xff0c;我们…

【蓝桥杯】线段树

一.线段树 1.定义&#xff1a; 线段树是算法竞赛中常用的用来维护 区间信息 的数据结构。 线段树可以在O(logN) 的时间复杂度内实现单点修改、区间修改、区间查询&#xff08;区间求和&#xff0c;求区间最大值&#xff0c;求区间最小值&#xff09;等操作。 2.结构&#x…

【论文阅读】Improved Denoising Diffusion Probabilistic Models

Improved Denoising Diffusion Probabilistic Models 文章目录 Improved Denoising Diffusion Probabilistic Models概述Improving the Log-likelihoodLearning ∑ θ ( x t , t ) \sum_{\theta}(x_{t}, t) ∑θ​(xt​,t)Improving the Noise ScheduleReducing Gradient Nois…

基于Pnpm + Turborepo + QianKun的微前端+Monorepo实践

基于Pnpm Turborepo QianKun的微前端Monorepo实践 背景 微前端一般都会涉及多个代码库&#xff0c;很多时候要一个一个代码库地去开发维护和运行&#xff0c;很不方便&#xff0c;这种时候引入Monorepo搭配微前端就能很好地解决这种问题&#xff0c;一个代码库就可以完成整…

Spring Cloud Alibaba微服务从入门到进阶(三)(Spring Cloud Alibaba)

Spring Cloud Alibaba是spring Cloud的子项目 Spring Cloud Alibaba的主要组件&#xff08;红框内是开源的&#xff09; Spring Cloud是快速构建分布式系统的工具集&#xff0c; Spring Cloud提供了很多分布式功能 Spring Cloud常用子项目 项目整合 Spring Cloud Alibaba …

友塔游戏测试开发笔面经验

题目一 给定任意非负整数M&#xff0c;判断其能否表达为 M 2 ^a 2 ^b(a和b为非负整数)&#xff0c;若可以输出a和b&#xff0c;若不能输出-1&#xff1b; 例如&#xff1a; 输入&#xff1a;6 输出: “1 2” 分析&#xff1a; void findAB(int M){} 为解决问题的主函数 …

优选算法[1]

目录 1.双指针&#xff1b; 2.滑动窗口&#xff1b; 3.二分查找&#xff1b; 4.前缀和&#xff1b; 1.双指针&#xff1b; 包括对撞指针和快慢指针(一般用来循环&#xff09;&#xff1b; 题目类型&#xff1a;移动零&#xff0c;复写零&#xff0c;快乐数&#xff0c;盛…

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

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

Python中类方法和静态方法的区别你知道吗?

​1.类方法 通过 classmethod 装饰器修饰的方法就是类方法 类方法可以通过类名或对象名调用&#xff0c;但是一般情况下使用类名调用&#xff08;节省内存&#xff09; 类方法中没有self.在类方法中不可以使用其它对象的属性和方法 类方法中一般会有一个参数cls&#xff0c;…

Crc冗余校验码设计

串行电路的位置&#xff0c;有异或门的地方是1&#xff08;生成多项式&#xff09; 简单的来说&#xff0c;如果最高位Q4 为0 的话&#xff0c;那么直接和 0 进行异或的话&#xff0c;实现的也是自己本身&#xff0c;直接左移就可以了 如果最高是1的话&#xff0c;那么就要和生…

【数据结构与算法】:选择排序与快速排序

&#x1f525;个人主页&#xff1a; Quitecoder &#x1f525;专栏&#xff1a;数据结构与算法 我的博客即将同步至腾讯云开发者社区&#xff0c;邀请大家一同入驻&#xff1a;腾讯云 欢迎来到排序的第二个部分&#xff1a;选择排序与快速排序&#xff01; 目录 1.选择排序1.…

如何export windows中的环境变量

在大语言模型&#xff08;LLM&#xff09;学习过程中&#xff0c; 利用 jupyter 导入环境变量时出现以下问题&#xff0c; C:\Users\zhangxuantao>export SENSENOVA_SKxxxxxx export 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 原因是学习教程中用…