需求分析
探花交友项目中的圈子功能,类似于朋友圈,基本功能为:发布动态,浏览好友动态,浏览推荐动态,点赞、评论、喜欢、关注、等功能
发布动态:选择照片以及输入动态文字,点击发送按钮
好友:需要看见你的动态;陌生人:也可能看见你的动态(推荐系统分析给你推送)
发布动态表:往此表中插入动态数据(发布id,动态id-主键id)
好友关系表
好友时间线表:当前用户好友的动态数据表
相册表:当前用户自己的动态数据表
技术方案
采用mongodb+redis来实现,其中mongodb负责存储,redis负责缓存
发布动态,:发布表-保存动态数据、往相册表-保存我的动态,好友表-查询好友id、往好友时间线表-保存好友动态
查询好友动态:好友时间线表:根据当前用户id拼接集合名、发布表、用户信息表
查询推荐动态:推荐动态表:根据当前用户id查询推荐动态表获取到发布id、发布表、用户信息表
实现方案分析
所以对于存储而言,主要是核心的6张表:
-
发布表:记录了所有用户的发布的东西信息,如图片、视频等。
-
相册:相册是每个用户独立的,记录了该用户所发布的所有内容。
-
评论:针对某个具体发布的朋友评论和点赞操作。
-
时间线:所谓“刷朋友圈”,就是刷时间线,就是一个用户所有的朋友的发布内容。
-
好友表:记录好友关系
-
推荐圈子表:记录推荐动态表
发布流程
首先用户发布动态,将动态内容写入到发布表
然后,将发布的指向写入到自己的相册表中
最后,将发布的指向写入到好友的时间线中。
查看流程
流程说明:
-
用户查看动态,如果查看自己的动态,直接查询相册表即可
-
如果查看好友动态,查询时间线表即可
-
如果查看推荐动态,查看推荐表即可
由此可见,查看动态的成本较低,可以快速的查询到动态数据。
数据库表分析
发布表
#表名:quanzi_publish
{
"id":1,#主键id
"userId":1, #用户id
"text":"今天心情很好", #文本内容
"medias":"http://xxxx/x/y/z.jpg", #媒体数据,图片或小视频 url
"seeType":1, #谁可以看,1-公开,2-私密,3-部分可见,4-不给谁看
"seeList":[1,2,3], #部分可见的列表
"notSeeList":[4,5,6],#不给谁看的列表
"longitude":108.840974298098,#经度
"latitude":34.2789316522934,#纬度
"locationName":"上海市浦东区", #位置名称
"created",1568012791171 #发布时间
}
相册表
#表名:quanzi_album_{userId}
{
"id":1,#主键id
"publishId":1001, #发布id
"created":1568012791171 #发布时间
}
时间线表
#表名:quanzi_time_line_{userId}
{
"id":1,#主键id,
"userId":2, #好友id
"publishId":1001, #发布id
"date":1568012791171 #发布时间
}
评论表
#表名:quanzi_comment
{
"id":1, #主键id
"publishId":1001, #发布id
"commentType":1, #评论类型,1-点赞,2-评论,3-喜欢
"content":"给力!", #评论内容
"userId":2, #评论人
"isParent":false, #是否为父节点,默认是否
"parentId":1001, #父节点id
"created":1568012791171
}
好友表
#表名:tanhua_users
{
"id":1, #主键id
"userId":1001, #用户id
"friendId":1, #好友id
"created":1568012791171
}
推荐动态表
#表名:recommend_quanzi
{
"id" : 1, #主键id
"userId" : 1001, #用户id
"score" : 9.0,
"created" : 1568012791171,
"publishId":1001, #发布id
}
实体类与vo
tanhua-domain模块mongo包中创建以下实体对象
Publish
package com.tanhua.domain.mongo;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.List;
/**
* <p>
* 发布的动态信息表
* </p>
*/
@Data
@Document(collection = "quanzi_publish")
public class Publish implements Serializable {
private ObjectId id; //主键id
private Long pid; //Long类型,用于推荐系统的模型
private Long userId;
private String textContent; //文字
private List<String> medias; //媒体数据,图片或小视频 url
private Integer seeType; // 谁可以看,1-公开,2-私密,3-部分可见,4-不给谁看
private String longitude; //经度
private String latitude; //纬度
private String locationName; //位置名称
private Long created; //发布时间
private Integer likeCount=0; //点赞数
private Integer commentCount=0; //评论数
private Integer loveCount=0; //喜欢数
}
Album
package com.tanhua.domain.mongo;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* <p>
* 相册表,用于存储自己发布的数据,每一个用户一张表进行存储
* </p>
*/
@Data
public class Album implements Serializable {
private ObjectId id; //主键id
private ObjectId publishId; //发布id
private Long created; //发布时间
}
TimeLine
package com.tanhua.domain.mongo;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* <p>
* 时间线表,用于存储发布(或推荐)的数据,每一个用户一张表进行存储
* </p>
*/
@Data
public class TimeLine implements Serializable {
private ObjectId id;
private Long userId; // 好友id
private ObjectId publishId; //发布id
private Long created; //发布的时间
}
Friend
package com.tanhua.domain.mongo;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* <p>
* 好友关系
* </p>
*/
@Data
@Document(collection = "tanhua_users")
public class Friend implements Serializable {
private ObjectId id;
private Long userId; //用户id
private Long friendId; //好友id
private Long created; //时间
}
RecommendQuanzi
package com.tanhua.domain.mongo;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* <p>
* 推荐动态
* </p>
*/
@Data
@Document(collection = "recommend_quanzi")
public class RecommendQuanzi implements Serializable {
@Id
private ObjectId id; // 主键
@Indexed
private Long userId; // 推荐的用户id
private Long pid;
private ObjectId publishId; // 发布的动态的id
@Indexed
private Double score = 0d; // 推荐分数
private Long created; // 日期
}
PublishVo
package com.tanhua.domain.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class PublishVo implements Serializable {
private Long userId; // 用户id
private String textContent; // 文本内容
private String location; // 地理位置
private String longitude; // 经度
private String latitude; // 纬度
private List<String> medias; // 图片url
}
MomentVo
package com.tanhua.domain.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class MomentVo implements Serializable {
private String id; //动态id
private Long userId; //用户id
private String avatar; //头像
private String nickname; //昵称
private String gender; //性别 man woman
private Integer age; //年龄
private String[] tags; //标签
private String textContent; //文字动态
private String[] imageContent; //图片动态
private String distance; //距离
private String createDate; //发布时间 如: 10分钟前
private int likeCount; //点赞数
private int commentCount; //评论数
private int loveCount; //喜欢数
private Integer hasLiked; //是否点赞(1是,0否)
private Integer hasLoved; //是否喜欢(1是,0否)
}
app发送请求,服务消费者接收请求,发布动态保存到动态表,保存到自己的相册表(动态表)根据登录用户id来查询好友id,再将发布信息保存到时间线表中
服务端
PublishApi
package com.tanhua.dubbo.api.mongo;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVo;
/**
* 圈子服务接口
*/
public interface PublishApi {
/**
* 发布动态
*/
String savePublish(PublishVo publishVo);
/**
* 好友动态
*/
PageResult<Publish> queryPublishByPage(int page, int pagesize, Long userId);
/**
* 推荐动态(陌生人动态)
*/
PageResult<Publish> queryPublishByRecommendQuanzi(int page, int pagesize, Long userId);
/**
* 用户动态
* 1.首页推荐用户列表-点击用户进入会查询用户动态
* 2.我的模块-我的动态-查看当前用户动态
*/
PageResult<Publish> queryPublishByAlbum(int page, int pagesize, Long userId);
/**
* 单条动态查询
*/
Publish querySinglePublish(String publishId);
/**
* 根据发布id更新动态状态
* @param publishId
* @param state
*/
void updatePublish(String publishId, Integer state);
}
PublishApiImpl
package com.tanhua.dubbo.api.mongo;
import com.tanhua.domain.mongo.*;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVo;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 圈子服务实现类
* 发布动态
* 好友动态
* 推荐动态
*/
@Service
public class PublishApiImpl implements PublishApi{
@Autowired
private MongoTemplate mongoTemplate;
/**
* 发布动态
*/
@Override
public String savePublish(PublishVo publishVo) {
Long currentUserId = publishVo.getUserId();//当前用户id
long nowTime = System.currentTimeMillis();
//1.发布动态表-保存
Publish publish = new Publish();
BeanUtils.copyProperties(publishVo,publish);//userId textContent longitude latitude medias
publish.setId(ObjectId.get());//手动设置id
publish.setPid(1l);//没有用到
publish.setSeeType(1);//公开
publish.setLocationName(publishVo.getLocation());//位置名称
publish.setCreated(nowTime);//发布动态时间
mongoTemplate.save(publish);
//2.相册表-保存 quanzi_album_2
Album album = new Album();
album.setPublishId(publish.getId());//发布id
album.setCreated(nowTime);//创建时间
mongoTemplate.save(album,"quanzi_album_"+currentUserId);//我的相册表
//3.好友表-查询好友ids tanhua_users(异步处理-进行解耦-MQ)
Query queryFriend = new Query();
queryFriend.addCriteria(Criteria.where("userId").is(currentUserId));
List<Friend> friendList = mongoTemplate.find(queryFriend, Friend.class);
if(!CollectionUtils.isEmpty(friendList)){
for (Friend friend : friendList) {
Long friendId = friend.getFriendId();//好友id
//4.好友时间线表-保存 quanzi_time_line_1
TimeLine timeLine = new TimeLine();
timeLine.setUserId(currentUserId);//好友id
timeLine.setPublishId(publish.getId());//发布id
timeLine.setCreated(nowTime);//创建时间
mongoTemplate.save(timeLine,"quanzi_time_line_"+friendId);//好友时间线表
}
}
return publish.getId().toHexString();
}
/**
* 好友动态
*/
@Override
public PageResult<Publish> queryPublishByPage(int page, int pagesize, Long userId) {
//1.分页查询时间线表
Query query = new Query();
query.limit(pagesize).skip((page-1)*pagesize);
query.with(Sort.by(Sort.Direction.DESC,"created"));//降序 将时间最新的在最上面展示
long counts = mongoTemplate.count(query, "quanzi_time_line_" + userId);
List<TimeLine> timeLineList = mongoTemplate.find(query,TimeLine.class,"quanzi_time_line_" + userId);
//2.根据时间线表中 发布id 查询发布表数据
//将 List<TimeLine>转为List<Publish>
List<Publish> publishList = new ArrayList<>();
if(!CollectionUtils.isEmpty(timeLineList)){
for (TimeLine timeLine : timeLineList) {
ObjectId publishId = timeLine.getPublishId();//发布id
Publish publish = mongoTemplate.findById(publishId, Publish.class);
if(!StringUtils.isEmpty(publish)) {
publishList.add(publish);
}
}
}
//3.封装分页对象返回
long pages = (counts / pagesize) + (counts%pagesize > 0 ? 1:0);
return new PageResult<>(counts,(long)pagesize,pages,(long)page,publishList);
}
/**
* 推荐动态(陌生人动态)
*/
@Override
public PageResult<Publish> queryPublishByRecommendQuanzi(int page, int pagesize, Long userId) {
//1.分页查询推荐动态表
Query query = new Query();
query.limit(pagesize).skip((page-1)*pagesize);
query.addCriteria(Criteria.where("userId").is(userId));//根据userId查询
query.with(Sort.by(Sort.Direction.DESC,"created"));//降序 将时间最新的在最上面展示
long counts = mongoTemplate.count(query, RecommendQuanzi.class);
List<RecommendQuanzi> recommendQuanziList = mongoTemplate.find(query,RecommendQuanzi.class);
//2.根据时间线表中 发布id 查询发布表数据
//将 List<RecommendQuanzi>转为List<Publish>
List<Publish> publishList = new ArrayList<>();
if(!CollectionUtils.isEmpty(recommendQuanziList)){
for (RecommendQuanzi recommendQuanzi : recommendQuanziList) {
ObjectId publishId = recommendQuanzi.getPublishId();//发布id
Publish publish = mongoTemplate.findById(publishId, Publish.class);
if(!StringUtils.isEmpty(publish)) {
publishList.add(publish);
}
}
}
//3.封装分页对象返回
long pages = (counts / pagesize) + (counts%pagesize > 0 ? 1:0);
return new PageResult<>(counts,(long)pagesize,pages,(long)page,publishList);
}
/**
* 用户动态
* 1.首页推荐用户列表-点击用户进入会查询用户动态
* 2.我的模块-我的动态-查看当前用户动态
*/
@Override
public PageResult<Publish> queryPublishByAlbum(int page, int pagesize, Long userId) {
//1.分页查询相册表
Query query = new Query();
query.limit(pagesize).skip((page-1)*pagesize);
query.with(Sort.by(Sort.Direction.DESC,"created"));//降序 将时间最新的在最上面展示
long counts = mongoTemplate.count(query, "quanzi_album_"+userId);//
List<Album> albumList = mongoTemplate.find(query,Album.class,"quanzi_album_"+userId);
//2.根据相册表中的 发布id 查询发布表数据
//将 List<Album>转为List<Publish>
List<Publish> publishList = new ArrayList<>();
if(!CollectionUtils.isEmpty(albumList)){
for (Album album : albumList) {//循环遍历相册表 根据发布id查询动态发布表
ObjectId publishId = album.getPublishId();//发布id
Publish publish = mongoTemplate.findById(publishId, Publish.class);
if(!StringUtils.isEmpty(publish)) {
publishList.add(publish);
}
}
}
//3.封装分页对象返回
long pages = (counts / pagesize) + (counts%pagesize > 0 ? 1:0);
return new PageResult<>(counts,(long)pagesize,pages,(long)page,publishList);
}
/**
* 单条动态查询
*/
@Override
public Publish querySinglePublish(String publishId) {
return mongoTemplate.findById(new ObjectId(publishId), Publish.class);
}
/**
* 根据发布id更新动态状态
* @param publishId
* @param state
*/
@Override
public void updatePublish(String publishId, Integer state) {
Query query = new Query();
query.addCriteria(Criteria.where("id").is(new ObjectId(publishId)));
Update update = new Update();
update.set("state",state);
mongoTemplate.updateFirst(query,update,Publish.class);
}
}
消费者
package com.tanhua.server.controller;
import com.tanhua.domain.vo.*;
import com.tanhua.server.service.MomentService;
import com.tanhua.server.service.TodayBestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 圈子功能控制层
*/
@RestController
@RequestMapping("/movements")
public class MomentController {
@Autowired
private MomentService momentService;
/**
* 发布动态
*/
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity savePublish(PublishVo publishVo,MultipartFile[] imageContent) {
momentService.savePublish(imageContent,publishVo);
return ResponseEntity.ok(null);
}
/**
* 好友动态
*/
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity queryPublishByPage(@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int pagesize) {
PageResult<MomentVo> pageResult = momentService.queryPublishByPage(page,pagesize);
return ResponseEntity.ok(pageResult);
}
/**
* 推荐动态(陌生人动态)
*/
@RequestMapping(value = "/recommend",method = RequestMethod.GET)
public ResponseEntity queryPublishByRecommendQuanzi(@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int pagesize) {
PageResult<MomentVo> pageResult = momentService.queryPublishByRecommendQuanzi(page,pagesize);
return ResponseEntity.ok(pageResult);
}
/**
* 用户动态
* 1.首页推荐用户列表-点击用户进入会查询用户动态
* 2.我的模块-我的动态-查看当前用户动态
*/
@RequestMapping(value = "/all",method = RequestMethod.GET)
public ResponseEntity queryPublishByAlbum(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int pagesize,Long userId) {
PageResult<MomentVo> pageResult = momentService.queryPublishByAlbum(page,pagesize,userId);
return ResponseEntity.ok(pageResult);
}
/**
* 动态点赞
* publishId:动态id
*/
@RequestMapping(value = "/{id}/like",method = RequestMethod.GET)
public ResponseEntity saveComment(@PathVariable("id") String publishId ) {
int likeCount = momentService.saveComment(publishId);
return ResponseEntity.ok(likeCount);
}
/**
* 动态取消点赞
* publishId:动态id
*/
@RequestMapping(value = "/{id}/dislike",method = RequestMethod.GET)
public ResponseEntity removeComment(@PathVariable("id") String publishId ) {
int likeCount = momentService.removeComment(publishId);
return ResponseEntity.ok(likeCount);
}
/**
* 动态喜欢
* publishId:动态id
*/
@RequestMapping(value = "/{id}/love",method = RequestMethod.GET)
public ResponseEntity saveCommentLove(@PathVariable("id") String publishId ) {
int loveCount = momentService.saveCommentLove(publishId);
return ResponseEntity.ok(loveCount);
}
/**
* 动态取消喜欢
* publishId:动态id
*/
@RequestMapping(value = "/{id}/unlove",method = RequestMethod.GET)
public ResponseEntity saveCommentUnLove(@PathVariable("id") String publishId ) {
int unLoveCount = momentService.saveCommentUnLove(publishId);
return ResponseEntity.ok(unLoveCount);
}
/**
* 单条动态查询
*/
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public ResponseEntity querySinglePublish(@PathVariable("id") String publishId) {
MomentVo momentVo = momentService.querySinglePublish(publishId);
return ResponseEntity.ok(momentVo);
}
/**
* 谁看过我(查询5条)
* http://localhost:10880/movements/visitors
*/
@RequestMapping(value = "/visitors",method = RequestMethod.GET)
public ResponseEntity queryVisitors() {
List<VisitorVo> visitorVoList = momentService.queryVisitors();
return ResponseEntity.ok(visitorVoList);
}
}
MomentService
package com.tanhua.server.service;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitor;
import com.tanhua.domain.vo.*;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.CommentApi;
import com.tanhua.dubbo.api.mongo.PublishApi;
import com.tanhua.dubbo.api.mongo.VisitorsApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 圈子业务逻辑处理层
*/
@Service
public class MomentService {
@Reference
private PublishApi publishApi;
@Reference
private UserInfoApi userInfoApi;
@Reference
private VisitorsApi visitorsApi;
@Autowired
private OssTemplate ossTemplate;
@Reference
private CommentApi commentApi;
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 发布动态
*/
public void savePublish(MultipartFile[] imageContent, PublishVo publishVo) {
try {
Long userId = UserHolder.getUserId();
//1.调用Oss组件上图图片
List<String> medias = new ArrayList<>();
//1.如果不为空
if(imageContent != null) {
//将图片遍历存入,阿里云图片
for (MultipartFile file : imageContent) {
String imageUrl = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
medias.add(imageUrl);
}
publishVo.setMedias(medias);//图片urls
}
publishVo.setUserId(userId);//当前发布动态用户id
//发布动态返回一个publishId
String publishId = publishApi.savePublish(publishVo);
//发送消息到中间件
rocketMQTemplate.convertAndSend("tanhua-publish",publishId);
} catch (IOException e) {
throw new TanHuaException(ErrorResult.error());
}
}
/**
* 好友动态
*/
public PageResult<MomentVo> queryPublishByPage(int page, int pagesize) {
PageResult<MomentVo> voPageResult = new PageResult<>();
Long userId = UserHolder.getUserId();
//a.调用服务:分页查询发布表数据(分别查询好友时间线表 发布表)
PageResult<Publish> publishPageResult = publishApi.queryPublishByPage(page,pagesize,userId);
if(publishPageResult == null || CollectionUtils.isEmpty(publishPageResult.getItems())){
return new PageResult<>(0l,10l,0l,0l,null);
}
//b.调用服务:根据发布用户id 查询用户信息
List<Publish> publishList = publishPageResult.getItems();
//将List<Publish>转为List<MomentVo>
List<MomentVo> momentVoList = new ArrayList<>();//返回给app集合
for (Publish publish : publishList) {
MomentVo momentVo = new MomentVo();
Long publishUserId = publish.getUserId();//发布动态用户id
UserInfo userInfo = userInfoApi.queryUserInfo(publishUserId);
BeanUtils.copyProperties(userInfo,momentVo);//头像 昵称 性别 年龄
BeanUtils.copyProperties(publish,momentVo);//文字动态、 点赞 评论 喜欢数
momentVo.setImageContent(publish.getMedias().toArray(new String[]{}));//图片urls地址
momentVo.setDistance("1米");//距离1米
momentVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));//发布动态时间
if(!StringUtils.isEmpty(userInfo.getTags())){
momentVo.setTags(userInfo.getTags().split(","));
}
momentVo.setId(publish.getId().toHexString());//动态id
momentVo.setUserId(userInfo.getId());//当前发布动态用户id
String key = "comment_"+userId+"_"+publish.getId().toHexString();
if(StringUtils.isEmpty(redisTemplate.opsForValue().get(key))){
momentVo.setHasLiked(0);是否点赞(1是,0否)
}else
{
momentVo.setHasLiked(1);是否点赞(1是,0否)
}
momentVoList.add(momentVo);
}
//c.将以上发布数据与用户信息封装Vo返回
BeanUtils.copyProperties(publishPageResult,voPageResult);
voPageResult.setItems(momentVoList);
return voPageResult;
}
/**
* 推荐动态(陌生人动态)
*/
public PageResult<MomentVo> queryPublishByRecommendQuanzi(int page, int pagesize) {
PageResult<MomentVo> voPageResult = new PageResult<>();
Long userId = UserHolder.getUserId();
//a.调用服务:分页查询发布表数据(分别查询好友时间线表 发布表)
PageResult<Publish> publishPageResult = publishApi.queryPublishByRecommendQuanzi(page,pagesize,userId);
if(publishPageResult == null || CollectionUtils.isEmpty(publishPageResult.getItems())){
return new PageResult<>(0l,10l,0l,0l,null);
}
//b.调用服务:根据发布用户id 查询用户信息
List<Publish> publishList = publishPageResult.getItems();
//将List<Publish>转为List<MomentVo>
List<MomentVo> momentVoList = new ArrayList<>();//返回给app集合
for (Publish publish : publishList) {
MomentVo momentVo = new MomentVo();
Long publishUserId = publish.getUserId();//发布动态用户id
UserInfo userInfo = userInfoApi.queryUserInfo(publishUserId);
BeanUtils.copyProperties(userInfo,momentVo);//头像 昵称 性别 年龄
BeanUtils.copyProperties(publish,momentVo);//文字动态、 点赞 评论 喜欢数
momentVo.setImageContent(publish.getMedias().toArray(new String[]{}));//图片urls地址
momentVo.setDistance("1米");//距离1米
momentVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));//发布动态时间
if(!StringUtils.isEmpty(userInfo.getTags())){
momentVo.setTags(userInfo.getTags().split(","));
}
momentVo.setId(publish.getId().toHexString());//动态id
momentVo.setUserId(userInfo.getId());//当前发布动态用户id
String key2 = "love_"+userId+"_"+publish.getId().toHexString();
if(StringUtils.isEmpty(redisTemplate.opsForValue().get(key2))) {
momentVo.setHasLoved(0);是否喜欢(1是,0否)
}else
{
momentVo.setHasLoved(1);是否喜欢(1是,0否)
}
String key = "comment_"+userId+"_"+publish.getId().toHexString();
if(StringUtils.isEmpty(redisTemplate.opsForValue().get(key))){
momentVo.setHasLiked(0);是否点赞(1是,0否)
}else
{
momentVo.setHasLiked(1);是否点赞(1是,0否)
}
momentVoList.add(momentVo);
}
//c.将以上发布数据与用户信息封装Vo返回
BeanUtils.copyProperties(publishPageResult,voPageResult);
voPageResult.setItems(momentVoList);
return voPageResult;
}
/**
* 用户动态
* 1.首页推荐用户列表-点击用户进入会查询用户动态
* 2.我的模块-我的动态-查看当前用户动态
*/
public PageResult<MomentVo> queryPublishByAlbum(int page, int pagesize, Long userId) {
PageResult<MomentVo> voPageResult = new PageResult<>();
//a.调用服务:分页查询发布表数据(分别查询好友时间线表 发布表)
PageResult<Publish> publishPageResult = publishApi.queryPublishByAlbum(page,pagesize,userId);
if(publishPageResult == null || CollectionUtils.isEmpty(publishPageResult.getItems())){
return new PageResult<>(0l,10l,0l,0l,null);
}
//b.调用服务:根据发布用户id 查询用户信息
List<Publish> publishList = publishPageResult.getItems();
//将List<Publish>转为List<MomentVo>
List<MomentVo> momentVoList = new ArrayList<>();//返回给app集合
for (Publish publish : publishList) {
MomentVo momentVo = new MomentVo();
Long publishUserId = publish.getUserId();//发布动态用户id
UserInfo userInfo = userInfoApi.queryUserInfo(publishUserId);
BeanUtils.copyProperties(userInfo,momentVo);//头像 昵称 性别 年龄
BeanUtils.copyProperties(publish,momentVo);//文字动态、 点赞 评论 喜欢数
momentVo.setImageContent(publish.getMedias().toArray(new String[]{}));//图片urls地址
momentVo.setDistance("1米");//距离1米
momentVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));//发布动态时间
if(!StringUtils.isEmpty(userInfo.getTags())){
momentVo.setTags(userInfo.getTags().split(","));
}
momentVo.setId(publish.getId().toHexString());//动态id
momentVo.setUserId(userInfo.getId());//当前发布动态用户id
String key = "comment_"+userId+"_"+publish.getId().toHexString();
if(StringUtils.isEmpty(redisTemplate.opsForValue().get(key))){
momentVo.setHasLiked(0);是否点赞(1是,0否)
}else
{
momentVo.setHasLiked(1);是否点赞(1是,0否)
}
momentVoList.add(momentVo);
}
//c.将以上发布数据与用户信息封装Vo返回
BeanUtils.copyProperties(publishPageResult,voPageResult);
voPageResult.setItems(momentVoList);
return voPageResult;
}
/**
* 动态点赞
* publishId:动态id
*/
public int saveComment(String publishId) {
Long userId = UserHolder.getUserId();//当前用户id
//a.服务提供者:点赞服务方法 返回点赞数量
Comment comment = new Comment();
comment.setPublishId(new ObjectId(publishId));//将String类型的发布id 转为ObjectId类型
comment.setCommentType(1);//评论类型,1-点赞,2-评论,3-喜欢
comment.setPubType(1);//评论内容类型: 1-对动态操作 2-对视频操作 3-对评论操作
comment.setUserId(userId);//当前点赞用户id
if(comment.getPubType() == 1){
//根据发布id查询发布表 获取userId(PublishUserId)
Publish publish = publishApi.querySinglePublish(publishId);
comment.setPublishUserId(publish.getUserId());//被评论的用户id
}
int likeCount = commentApi.saveComment(comment);
//b.将点赞记录写入redis
String key = "comment_"+userId+"_"+publishId;//保证唯一 业务前缀标识+userId+publishId
redisTemplate.opsForValue().set(key,"1");
//c.将点赞数封装返回给app展示
return likeCount;
}
/**
* 动态取消点赞
* publishId:动态id
*/
public int removeComment(String publishId) {
Long userId = UserHolder.getUserId();
//a.服务提供者:取消点赞服务方法 返回点赞数量
Comment comment = new Comment();
comment.setPublishId(new ObjectId(publishId));//动态id
comment.setCommentType(1);//评论类型,1-点赞,2-评论,3-喜欢
comment.setPubType(1);//评论内容类型: 1-对动态操作 2-对视频操作 3-对评论操作
comment.setUserId(userId);//userId
int likeCount = commentApi.removeComment(comment);
//b.将点赞记录从redis删除
String key = "comment_"+userId+"_"+publishId;//保证唯一 业务前缀标识+userId+publishId
redisTemplate.delete(key);
//c.将点赞数封装返回给app展示
return likeCount;
}
/**
* 动态喜欢
* publishId:动态id
*/
public int saveCommentLove(String publishId) {
Long userId = UserHolder.getUserId();//当前用户id
//a.服务提供者:点赞服务方法 返回点赞数量
Comment comment = new Comment();
comment.setPublishId(new ObjectId(publishId));//将String类型的发布id 转为ObjectId类型
comment.setCommentType(3);//评论类型,1-点赞,2-评论,3-喜欢
comment.setPubType(1);//评论内容类型: 1-对动态操作 2-对视频操作 3-对评论操作
comment.setUserId(userId);//当前点赞用户id
if(comment.getPubType() == 1){
//根据发布id查询发布表 获取userId(PublishUserId)
Publish publish = publishApi.querySinglePublish(publishId);
comment.setPublishUserId(publish.getUserId());//被评论的用户id
}
int likeCount = commentApi.saveComment(comment);
//b.将点赞记录写入redis
String key = "love_"+userId+"_"+publishId;//保证唯一 业务前缀标识+userId+publishId
redisTemplate.opsForValue().set(key,"1");
//c.将点赞数封装返回给app展示
return likeCount;
}
/**
* 动态取消喜欢
* publishId:动态id
*/
public int saveCommentUnLove(String publishId) {
Long userId = UserHolder.getUserId();
//a.服务提供者:取消点赞服务方法 返回点赞数量
Comment comment = new Comment();
comment.setPublishId(new ObjectId(publishId));//动态id
comment.setCommentType(3);//评论类型,1-点赞,2-评论,3-喜欢
comment.setPubType(1);//评论内容类型: 1-对动态操作 2-对视频操作 3-对评论操作
comment.setUserId(userId);//userId
int likeCount = commentApi.removeComment(comment);
//b.将点赞记录从redis删除
String key = "love_"+userId+"_"+publishId;//保证唯一 业务前缀标识+userId+publishId
redisTemplate.delete(key);
//c.将点赞数封装返回给app展示
return likeCount;
}
/**
* 单条动态查询
*/
public MomentVo querySinglePublish(String publishId) {
//a.调用服务:根据发布id查询动态发布表
Publish publish = publishApi.querySinglePublish(publishId);
if(publish == null){
return null;
}
//b.调用服务:根据发布用户id 查询用户信息
//将List<Publish>转为List<MomentVo>
MomentVo momentVo = new MomentVo();
Long publishUserId = publish.getUserId();//发布动态用户id
UserInfo userInfo = userInfoApi.queryUserInfo(publishUserId);
BeanUtils.copyProperties(userInfo,momentVo);//头像 昵称 性别 年龄
BeanUtils.copyProperties(publish,momentVo);//文字动态、 点赞 评论 喜欢数
momentVo.setImageContent(publish.getMedias().toArray(new String[]{}));//图片urls地址
momentVo.setDistance("1米");//距离1米
momentVo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));//发布动态时间
if(!StringUtils.isEmpty(userInfo.getTags())){
momentVo.setTags(userInfo.getTags().split(","));
}
momentVo.setId(publish.getId().toHexString());//动态id
momentVo.setUserId(userInfo.getId());//当前发布动态用户id
return momentVo;
}
/**
* 谁看过我(查询5条)
*/
public List<VisitorVo> queryVisitors() {
List<VisitorVo> list = new ArrayList<>();
Long userId = UserHolder.getUserId();//当前用户登录id
//a.查询redis上次登录时间是否存在
String key="visitors_time_"+userId;
String lastLoginTime = redisTemplate.opsForValue().get(key);//key:visitors_time_1 value:上次登录的时间
///b.如果上次登录时间存在,date(访客访问时间)>上次登录时间5条记录
List<Visitor> visitorList = new ArrayList<>();
if(!StringUtils.isEmpty(lastLoginTime)){
//将String lastLoginTime转为Long lastLoginTime
long lastLoginTimeLong = Long.parseLong(lastLoginTime);
visitorList = visitorsApi.queryVisitorsByDate(lastLoginTimeLong,userId);
}else {
//c.如果上次登录时间不存在,从所有访客记录中查询5条记录
visitorList = visitorsApi.queryVisitors(userId);
}
for (Visitor visitor : visitorList) {
VisitorVo visitorVo = new VisitorVo();
UserInfo userInfo = userInfoApi.queryUserInfo(visitor.getVisitorUserId());
BeanUtils.copyProperties(userInfo,visitorVo);//头像 昵称 性别 年龄
visitorVo.setTags(userInfo.getTags().split(","));//标签
visitorVo.setId(visitor.getVisitorUserId());//访客用户id
visitorVo.setFateValue(visitor.getScore().intValue());//访客表中缘分值
list.add(visitorVo);
}
//d.将当前登录时间记录redis
redisTemplate.opsForValue().set(key,System.currentTimeMillis()+"");
return list;
}
}