博客网站的文章推荐实现
做了一个博客网站,基本功能就是实现用户查找文章,查看文章内容。后面想到增加实现能够根据用户的喜好程度不同来推荐不同的文章,希望看完能对你有所帮助。
简述一下本网站实现推荐的过程是如何进行的。
首先定义好推荐数据的依据,对文章数据库中设置keyWord字段,用于存储文章的话题或者标签,每个文章存储的话题有多个由发布文章时由作者设定,以下为数据库存储文章标签的字段。

其次设计一个喜好的程度的方案,用户对文章在不同时期对文章做的不同操作表现出用户对该类型的文章喜好程序不一样,例如用户对文章的浏览、点赞、收藏、评论的行为加分权值为0.1、0.3、0.5、0.3,评论的加分权值可根据用户的内容来评判这里不作为详细处理统计评论就是加0.3分。由于用户存在喜新厌旧的情况,因此在收集用户的行为记录时需要按时间收集并且时间越长的行为权值越低,比如一个月以内的点赞权值为0.3*1,一个月后的点赞权值为0.3*0.6.
建立用户喜好分析模型UserAnalysisModel,该模型用于分析用户的某种(点赞评论等)行为的喜好偏好表,key为喜好标签名,value为权重值

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.yiqingxuan_article.content.bean.Article;//自定义实体类
import com.example.yiqingxuan_article.content.dao.ArticleMapper;//自定义DAO类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** @Author: 曾敏* @Description: 用户喜好分析模型* @DateTime: 2023/5/26 13:36**/
@Service
public class UserAnalysisModel {//Mapper层,用于从数据库中提取文章内容@Autowiredprivate ArticleMapper articleMapper;//redis@AutowiredRedisTemplate redisTemplate;public Map WeightTable;private List listone=new ArrayList<>();//用户第一个月的行为记录列表private List listtow=new ArrayList<>();//用户第二个月的行为记录列表private List listtree=new ArrayList<>();//用户第三个月及其以后的行为记录列表List listsum;//三个时间节点的文章id总和List listarticles;//存放用户的浏览记录文章Map> id_keymap;//存放文章号代表的关键字对照表private Integer userid;private double Weight;//当前分享的行为权值表private double ONE_MONTH=1;private double TOW_MONTH=0.6;private double TREE_MONTH=0.4;public Map execute(Integer uid,String type){if (type.equals("点赞")){Weight=0.5;}else if (type.equals("收藏")){Weight=0.3;}else if (type.equals("浏览")){Weight=0.1;}else if (type.equals("评论")){Weight=0.3;}else {return null;}userid=uid;//开始业务分析System.out.println("当前行为分析:"+type);GetMonthLists();GetArticleAndKeyTable();createWeightTable();Calculate();return WeightTable;}/*** 将三时期各种行为记录的set集合存入列表*/private void GetMonthLists(){String key;if (Weight==0.5){key="user_like_";}else if (Weight==0.4){key="user_store_";}else if (Weight==0.3){key="user_comment_";}else if (Weight==0.1){key="user_read_";}else {return;}//一个月内Set membersone= (Set) redisTemplate.opsForZSet().rangeByScore(key+userid, GetCurrentTimestamp(1), GetCurrentTimestamp(0)).stream().map(Object::toString).collect(Collectors.toSet());//一月到二月间Set memberstwo= (Set) redisTemplate.opsForZSet().rangeByScore(key+userid, GetCurrentTimestamp(2), GetCurrentTimestamp(1)).stream().map(Object::toString).collect(Collectors.toSet());//二月后Set memberstree= (Set) redisTemplate.opsForZSet().rangeByScore(key+userid, Double.MIN_VALUE, GetCurrentTimestamp(2)).stream().map(Object::toString).collect(Collectors.toSet());System.out.println("第一时期的"+Weight+"记录:"+membersone);if (membersone.size()>0||membersone!=null){for (String s:membersone){if (Weight==0.1||Weight==0.3){String [] parms=s.split("_");String result=parms[0];listone.add(Integer.valueOf(result));}else {listone.add(Integer.valueOf(s));}}while (listone.size() > 500) {//将数据采集量限制大小Random random = new Random();int indexToRemove = random.nextInt(listone.size());listone.remove(indexToRemove);}}//将set集合存入列表中if (membersone.size()>0||membersone!=null){for (String s:memberstwo){if (Weight==0.1||Weight==0.3){String [] parms=s.split("_");String result=parms[0];listone.add(Integer.valueOf(result));}else {listone.add(Integer.valueOf(s));}}while (listtow.size() > 400) {Random random = new Random();int indexToRemove = random.nextInt(listtow.size());listtow.remove(indexToRemove);}}if (membersone.size()>0||membersone!=null){for (String s:memberstree){if (Weight==0.1||Weight==0.3){String [] parms=s.split("_");String result=parms[0];listone.add(Integer.valueOf(result));}else {listone.add(Integer.valueOf(s));}}while (listtree.size() > 300) {Random random = new Random();int indexToRemove = random.nextInt(listtree.size());listtree.remove(indexToRemove);}}// 合并列表,只合并非空列表System.out.println("三个时期的表记录值:"+listone+"==="+listtow+"==="+listtree);listsum = Stream.of(listone, listtow, listtree).filter(list -> !list.isEmpty()).flatMap(list -> list.stream()).collect(Collectors.toList());}/*** 得到文章号与其关键字的对照表*/private void GetArticleAndKeyTable(){System.out.println(listsum);QueryWrapper wrapper = new QueryWrapper<>();wrapper.select("id", "keyWords").in("id", listsum);listarticles=articleMapper.selectList(wrapper);//获取结果集合System.out.println("用户看过的文章记录表:"+listarticles);Map> map1=new HashMap<>();for (Article article:listarticles){String keyWord=article.getKeywords();String [] keyWords=keyWord.split("#");int n=keyWords.length;String first = keyWords[0];for (int i=1;i list = Arrays.asList(keyWords);map1.put(article.getId(),list);}//得到文章号与其关键字的对照表System.out.println(map1.size());id_keymap=map1;}/*** 初始化用户喜好权值表,获取用户浏览过的标签生成map*/private void createWeightTable(){List listkeysum=new ArrayList<>();//当前用户的所有喜好集合Set set=id_keymap.keySet();for (Integer element : set) {List list=id_keymap.get(element);//得到当前文章号的标签集合Set tempset=new HashSet();tempset.addAll(listkeysum);tempset.addAll(list);listkeysum=new ArrayList<>(tempset);}Map map1=new HashMap<>();for (String s:listkeysum){map1.put(s,0.0);}WeightTable=map1;}/*** 为用户权值表计算*/private void Calculate(){if (listone.size()>0){System.out.println("用户浏览过的文章关键字合集:"+id_keymap);for (Integer i:listone){//一个月内的计算List listKeys=id_keymap.get(i);//得到一个关键字集合for (String s:listKeys){//Double initial=WeightTable.get(s);Double newvalue=initial+(Weight*ONE_MONTH);WeightTable.put(s,newvalue);}}}if (listtow.size()>0){for (Integer i:listtow){//一个月内的计算List listKeys=id_keymap.get(i);//得到一个关键字集合for (String s:listKeys){//Double initial=WeightTable.get(s);Double newvalue=initial+(Weight*TOW_MONTH);WeightTable.put(s,newvalue);}}}if (listtree.size()>0){for (Integer i:listtree){//一个月内的计算List listKeys=id_keymap.get(i);//得到一个关键字集合for (String s:listKeys){//Double initial=WeightTable.get(s);Double newvalue=initial+(Weight*TREE_MONTH);WeightTable.put(s,newvalue);}}}System.out.println("权值表:"+WeightTable);}/*** 输入获取的月份返回时间戳* @param i* @return*/public static long GetCurrentTimestamp(int i){// 获取当前时间戳long currentTimestamp = System.currentTimeMillis();// 获取一个月前的时间戳Calendar calendar = Calendar.getInstance();calendar.setTime(new Date(currentTimestamp));calendar.add(Calendar.MONTH, -1); // 减去一个月long oneMonthAgoTimestamp = calendar.getTimeInMillis();// 获取两个月前的时间戳calendar.add(Calendar.MONTH, -1); // 再减去一个月long twoMonthsAgoTimestamp = calendar.getTimeInMillis();if (i==0){return currentTimestamp;}else if (i==1){return oneMonthAgoTimestamp;}else if (i==2){return twoMonthsAgoTimestamp;}else {return 0;}}}
以上代码用于获取用户某个行为喜好权重表,具体推荐由以下代码进行
package com.example.yiqingxuan_article.content.service;import com.example.yiqingxuan_article.content.bean.Article;
import com.example.yiqingxuan_article.content.dao.ArticleMapper;
import com.example.yiqingxuan_article.content.dao.CategoryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.*;
import java.util.stream.Collectors;import static jdk.nashorn.internal.objects.Global.Infinity;/*** @Author: 曾敏* @Description: TODO* @DateTime: 2023/5/26 1:21**/
@Service
public class Recommend {@Autowiredprivate ArticleMapper articleMapper;@AutowiredRedisTemplate redisTemplate;@Autowiredprivate CategoryMapper categoryMapper;@Autowiredprivate UserAnalysisModel UserLike1;@Autowiredprivate UserAnalysisModel UserLike2;@Autowiredprivate UserAnalysisModel UserLike3;@Autowiredprivate UserAnalysisModel UserLike4;/*** 获取用户喜好列表内容* @param userid* @return*/public List GetUserLike(Integer userid){Map readmap=UserLike1.execute(userid,"浏览");Map givemap=UserLike2.execute(userid,"点赞");Map collecttmap=UserLike3.execute(userid,"收藏");Map commentmap=UserLike4.execute(userid,"评论");List
在控制层使用样式
@RestController
@RequestMapping("/selectarticle")
public class ArticleSelectControll { @Autowiredprivate Recommend recommend;/*** 传入用户id,返回推荐文章列表* @param userid* @return*/@GetMapping("/recommend")public jsonModel Recommend(@RequestParam Integer userid){jsonModel jsonModel=new jsonModel();System.out.println("推荐查询:"+userid);List list=recommend.SelectRecommend(userid);System.out.println(list);if (list.size()>0&&list!=null){jsonModel.setData(list);jsonModel.setCode(1);}else {jsonModel.setMsg("推荐失败");jsonModel.setCode(0);}return jsonModel;}
}
使用推荐算法时,后台算法细节

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
