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

随机匹配

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

匹配 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 的生命周期****列举一些重要…

20个最佳ChatGPT创业提示

20 Best ChatGPT Prompts for Start-Ups 在初创企业不断变化的生态系统中&#xff0c;利用像 ChatGPT 这样的尖端工具可以成为改变游戏规则的因素。初创企业以其敏捷性和创新性而闻名&#xff0c;总是在寻找提高效率、创造力和竞争力的方法。ChatGPT 凭借其先进的功能&#xf…

leetcode2684--矩阵中移动的最大次数

1. 题意 矩阵中一个位置只能从左上一、左、左下一格子转移而来&#xff0c;且当前值一定大于转移之前的值&#xff1b; 求从第一列开始的最大转移步数。 矩阵中移动的最大次数 2. 题解 思路 由于状态只能从左向右转移&#xff0c;所以同一个位置被搜索到后&#xff0c;第一…

一命通关差分

本章节是前缀和的延申 一命通关前缀和-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…

前端UNIAPP端webview嵌入H5使用说明文档

一、关闭webView窗口 plus.webview.close( id_wvobj, aniClose, duration, extras ); 功能说明 关闭已经打开的Webview窗口&#xff0c;需先获取窗口对象或窗口id&#xff0c;并可指定关闭窗口的动画及动画持续时间。 参数说明 参数是否必须参数类型/固定值说明id_wvobj是…

GPT-3后的下一步:大型语言模型的未来方向

摘要&#xff1a; 本文将概述GPT-3后的下一步&#xff1a;大型语言模型的未来方向&#xff0c;包括技术发展趋势、应用场景、挑战与机遇。 引言&#xff1a; GPT-3是OpenAI于2020年发布的一款大型语言模型&#xff0c;它在自然语言处理领域取得了突破性进展。GPT-3的出现标志…

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

全国农产品价格分析预测可视化系统设计与实现 【摘要】在当今信息化社会&#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;这篇文章…

Vue.js基础

表单输入绑定 基础用法 v-model 指令在表单 <input>、<textarea>及 <select> 元素上创建双向数据绑定。 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据&#xff0c;并对一些极端场景进行一些特殊处理。 vue 模板语法包括两大类 插值语法…

Java算法之数论基础

Java算法之数论基础 一、最大公约数&#xff08;Greatest Common Divisor, GCD&#xff09; 在Java中&#xff0c;我们可以使用欧几里得算法&#xff08;辗转相除法&#xff09;来求两个数的最大公约数&#xff1a; 辗转相除法&#xff08;欧几里得算法&#xff09; 辗转相…

会议室预约系统优化(蓝桥杯)

文章目录 会议室预约系统优化问题描述差分 会议室预约系统优化 问题描述 假设你是一家大型企业的 IT 工程师&#xff0c;企业内有 n 个会议室&#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…

C++/CLI学习笔记4(快速打通c++与c#相互调用的桥梁)

3.4声明多个变量 同一个语句可声明同类型的多个变量&#xff0c;用逗号分隔即可&#xff0c;如下所示:int x 10, y, z 11; 该语句声明int变量x,y和z。第一个初始化为10&#xff0c;第二个未初始化&#xff0c;第三个初始化为11。 3.5变量赋值 使用赋值操作符(等号)向变量…

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) …

ASR语音识别纠错-fast correct

1、使用方式说明 ASR对应的文本越长&#xff0c;识别准确率和召回率越高 识别的错误分类&#xff1a; 编号错误类型示例1谐音字词配副眼睛-配副眼镜2混淆音字词流浪织女-牛郎织女3多字错误关关机-关机4少字错误 爱有天意-假如爱有天意 5形似字错误高梁-高粱6中文拼音全拼xin…

二叉树【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…