为什么使用mogodb
数据量非常大
读多写少
价值较低
mongoDB数据结构非常类似于关系型数据库(数据类型非常丰富)
一条sql语句,单张表查询一定比多张表查询要快(设计表的时候尽量将数据设计到一张表,可以冗余字段)
什么是mongodb?
分步式文件存储c++高性能数据库(内存数据库,通过引擎异步同步数据到cipan)
通过docker安装mongoDB
#进入base目录 cd /root/docker-file/base/ #批量创建启动容器,其中已经包含了redis,zookeeper,mongodb容器 docker-compose up -d #查看容器 docker ps -a
支持的数据类型
null,布尔型,数值,字符串,日期,正则表达式,数组,内嵌文档,对象id,二进制数据
在mongodb中,存储的文档结构是类似于json的结构,称之为bson
springboot整合mongoDB
使用Spring-Data-MongoDB很简单,只需要如下几步即可:
导入依赖
<parent> ??? <groupId>org.springframework.boot</groupId> ??? <artifactId>spring-boot-starter-parent</artifactId> ??? <version>2.1.0.RELEASE</version> </parent>
<dependency> ???? <groupId>org.springframework.boot</groupId> ???? <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> ??? <groupId>org.springframework.boot</groupId> ??? <artifactId>spring-boot-starter-test</artifactId> ??? <scope>test</scope> </dependency>
?
编写application.yml配置文件
spring: ? data: ??? mongodb: ????? uri: mongodb://192.168.136.160:27017/test? #mongodb的数据库地址和名称
?探花今日佳人
今日佳人需求介绍
今日佳人功能分析
今日佳人功能实现
在用户登录成功之后,就会进入首页,首页有今日佳人,推荐好友,探花,搜附近等功能
今日佳人会根据缘分值最大的用户,进行展现出来。缘分值的计算是由用户的行为进行打分,如点赞评论学历婚姻状态等信息组合而成。
推荐结果是由大数据工程师来生成的,所以我们只需要从结果中查询到缘分值最高的用户就可以了。
当登录探花app后,在首页可以看到和自己最匹配的佳人信息(每天推荐的佳人是不一样的)首页佳人数据,是从推荐胸每天定时根据用户基本信息以及习惯,分析推荐类似用户。推荐系统会将分析结果写入一张表中,今日佳人表
服务提供者
1.根据当前用户id查询佳人用户信息
2.根据佳人用户id查询佳人用户信息
消费者
1.controller接收今日佳人请求
2.controller调用service业务处理
a.根据当前用户id 查询一条今日佳人数据(调用服务提供者) -- recommend_user
b.如果今日佳人数据不存在,则设置一条默认假数据(为了提升用户体验)
c.根据佳人用户id调用服务查询佳人用户信息 tb_userInfo
d.根据以上调用服务结果封装Vo返回
TodayBestVo
package com.tanhua.domain.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class TodayBestVo implements Serializable {
private Long id;
private String avatar;
private String nickname;
private String gender; //性别 man woman
private Integer age;
private String[] tags;
private Long fateValue; //缘分值
}
服务提供者-今日佳人
导入依赖
tanhua-domain模块的pom.xml引入mongo依赖
<!--SpringDataMongo起步依赖--> <dependency> ??? <groupId>org.springframework.boot</groupId> ??? <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <dependency> ?? ?<groupId>org.mongodb</groupId> ??? <artifactId>mongodb-driver-sync</artifactId> ??? <version>3.9.1</version> </dependency>
RecommendUser
package com.tanhua.dubbo.api.mongo;
import com.tanhua.domain.mongo.RecommendUser;
import com.tanhua.domain.vo.PageResult;
/**
* 佳人服务接口
*/
public interface RecommendUserApi {
/**
* 根据当前登录的用户id查询佳人用户表 最匹配用户对象(1条记录)
* @param toUserId
* @return
*/
RecommendUser queryMaxScoreByToUserId(Long toUserId);
/**
* 跟当前登录用户id 分页参数 分页查询佳人列表数据
* @param page
* @param pagesize
* @param currentUserId
* @return
*/
PageResult<RecommendUser> queryPageByUserId(Integer page, Integer pagesize, Long currentUserId);
/**
* 根据佳人用户id 与 当前用户id 查询缘分值
* @param userId 佳人用户id
* @param toUserId 当前用户id
* @return
*/
Double queryForScore(Long userId,Long toUserId);
}
RecommendUserApiImpl
package com.tanhua.dubbo.api.mongo;
import com.tanhua.domain.mongo.RecommendUser;
import com.tanhua.domain.vo.PageResult;
import org.apache.dubbo.config.annotation.Service;
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 java.util.List;
/**
* 今日佳人服务实现类
*/
@Service
public class RecommendUserApiImpl implements RecommendUserApi {
@Autowired
private MongoTemplate mongoTemplate;
/**
* 根据当前登录的用户id查询佳人用户表 最匹配用户对象(1条记录)
* db.recommend_user.find({toUserId:1}).sort({score:-1}).limit(1);
*
* @param toUserId
* @return
*/
@Override
public RecommendUser queryMaxScoreByToUserId(Long toUserId) {
Query query = new Query();
//{toUserId:1}
query.addCriteria(Criteria.where("toUserId").is(toUserId));
//sort({score:-1})
//query.with(Sort.by(Sort.Direction.DESC, "score"));
query.with(Sort.by(Sort.Direction.ASC, "userId"));
//limit(1)
query.limit(1);
return mongoTemplate.findOne(query, RecommendUser.class);
}
/**
* 跟当前登录用户id 分页参数 分页查询佳人列表数据
*
* @param page
* @param pagesize
* @param currentUserId
* @return
*/
@Override
public PageResult<RecommendUser> queryPageByUserId(Integer page, Integer pagesize, Long currentUserId) {
//1.查询recommendUser表总记录数
Query query = new Query();
query.addCriteria(Criteria.where("toUserId").is(currentUserId));//当前用户id
query.limit(pagesize).skip((page - 1) * pagesize);
long counts = mongoTemplate.count(query, RecommendUser.class);
//2.查询当前页面要展示的数据
List<RecommendUser> recommendUserList = mongoTemplate.find(query, RecommendUser.class);
//3.将数据封装返回
long pages = (counts / pagesize) + (counts%pagesize > 0 ? 1:0);
return new PageResult<>(counts,(long)pagesize,pages,(long)page,recommendUserList);
}
/**
* 根据佳人用户id 与 当前用户id 查询缘分值
* @param userId 佳人用户id
* @param toUserId 当前用户id
* @return
*/
@Override
public Double queryForScore(Long userId, Long toUserId) {
Query query = new Query();
//{toUserId:1}
query.addCriteria(Criteria.where("userId").is(userId).and("toUserId").is(toUserId));
RecommendUser recommendUser = mongoTemplate.findOne(query, RecommendUser.class);
if(recommendUser == null){
return 99d;
}
return recommendUser.getScore();
}
}
消费者
TodayBestController
package com.tanhua.server.controller;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.RecommendUserQueryParam;
import com.tanhua.domain.vo.TodayBestVo;
import com.tanhua.server.service.SettingService;
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 java.util.Map;
/**
* 今日佳人控制层
*/
@RestController
@RequestMapping("/tanhua")
public class TodayBestController {
@Autowired
private TodayBestService todayBestService;
/**
* 首页-今日佳人
*/
@RequestMapping(value = "/todayBest", method = RequestMethod.GET)
public ResponseEntity todayBest() {
TodayBestVo todayBestVo = todayBestService.todayBest();
return ResponseEntity.ok(todayBestVo);
}
/**
* 首页-佳人列表数据分页查询
*/
@RequestMapping(value = "/recommendation", method = RequestMethod.GET)
public ResponseEntity recommendation(RecommendUserQueryParam recommendUserQueryParam) {
PageResult<TodayBestVo> pageResult = todayBestService.recommendation(recommendUserQueryParam);
return ResponseEntity.ok(pageResult);
}
/**
* 查看用户详情
* {id}:佳人用户id
*/
@RequestMapping(value = "/{id}/personalInfo", method = RequestMethod.GET)
public ResponseEntity personalInfo(@PathVariable("id") Long personUserId) {
TodayBestVo todayBestVo = todayBestService.personalInfo(personUserId);
return ResponseEntity.ok(todayBestVo);
}
/**
* 查询陌生人问题
* userId:佳人用户id
*/
@RequestMapping(value = "/strangerQuestions", method = RequestMethod.GET)
public ResponseEntity strangerQuestions(Long userId) {
String txt = todayBestService.strangerQuestions(userId);
return ResponseEntity.ok(txt);
}
/**
* 回复陌生人问题
*/
@RequestMapping(value = "/strangerQuestions", method = RequestMethod.POST)
public ResponseEntity strangerQuestions(@RequestBody Map params) {
Long userId = Long.parseLong(params.get("userId").toString());
String reply = (String) params.get("reply");//回复内容
todayBestService.replyStrangerQuestions(userId, reply);
return ResponseEntity.ok(null);
}
/**
* 添加喜欢
*/
@GetMapping("/{id}/love")
public ResponseEntity addLikeUser(@PathVariable("id") String id) {
todayBestService.addLikeUser(Long.valueOf(id));
return ResponseEntity.ok(null);
}
/**
* 添加黑名单
*/
@GetMapping("/{id}/unlove")
public ResponseEntity unLikeUser(@PathVariable("id") String id) {
todayBestService.addBlackUser(Long.valueOf(id));
return ResponseEntity.ok(null);
}
}
TodayBestService
package com.tanhua.server.service;
import com.alibaba.fastjson.JSON;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.domain.db.BlackList;
import com.tanhua.domain.db.Question;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Friend;
import com.tanhua.domain.mongo.RecommendUser;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.RecommendUserQueryParam;
import com.tanhua.domain.vo.TodayBestVo;
import com.tanhua.dubbo.api.db.BlackListApi;
import com.tanhua.dubbo.api.db.QuestionApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 今日佳人业务处理层
*/
@Service
@Slf4j
public class TodayBestService {
@Reference
private RecommendUserApi recommendUserApi;
@Reference
private UserInfoApi userInfoApi;
@Reference
private BlackListApi blackListApi;
@Reference
private QuestionApi questionApi;
@Reference
private UserLikeApi userLikeApi;
@Reference
private FriendApi friendApi;
@Autowired
private HuanXinTemplate huanXinTemplate;
/**
* 首页-今日佳人
*/
public TodayBestVo todayBest() {
Long toUserId = UserHolder.getUserId();//当前登录用户id
//a.根据当前用户id 查询一条今日佳人数据(调用服务提供者) -- recommend_user
RecommendUser recommendUser = recommendUserApi.queryMaxScoreByToUserId(toUserId);
//b.如果今日佳人数据不存在,则设置一条默认假数据(为了提升用户体验)
if (recommendUser == null) {
//默认数据
recommendUser = new RecommendUser();
recommendUser.setUserId(1l);
recommendUser.setScore(99d);
}
//c.根据佳人用户id调用服务查询佳人用户信息 tb_userInfo
Long userId = recommendUser.getUserId();//佳人用户id
UserInfo userInfo = userInfoApi.queryUserInfo(userId);
//d.根据以上调用服务结果封装Vo返回
TodayBestVo todayBestVo = new TodayBestVo();
BeanUtils.copyProperties(userInfo, todayBestVo);
//设置tags
if (!StringUtils.isEmpty(userInfo.getTags())) {
todayBestVo.setTags(userInfo.getTags().split(","));
}
//设置缘分值
todayBestVo.setFateValue(recommendUser.getScore().longValue());
return todayBestVo;
}
/**
* 首页-佳人列表数据分页查询
*/
public PageResult<TodayBestVo> recommendation(RecommendUserQueryParam param) {
//定义返回PageResultVo
PageResult<TodayBestVo> voPageResult = new PageResult<>();
Long currentUserId = UserHolder.getUserId();
//1.跟当前登录用户id 分页参数 分页查询佳人列表数据
PageResult<RecommendUser> pageResult = recommendUserApi.queryPageByUserId(param.getPage(), param.getPagesize(), currentUserId);
//2.如果数据为空,设置默认数据
List<RecommendUser> recommendUserList = new ArrayList<>();
if (pageResult == null || CollectionUtils.isEmpty(pageResult.getItems())) {
recommendUserList = defaultRecommend();
} else {
recommendUserList = pageResult.getItems();
}
//3.根据userId查询userInfo
//4.将List<RecommendUser>转为List<TodayBestVo>
List<TodayBestVo> todayBestVoList = new ArrayList<>();
for (RecommendUser recommendUser : recommendUserList) {
//根据以上调用服务结果封装Vo返回
TodayBestVo todayBestVo = new TodayBestVo();
Long userId = recommendUser.getUserId();//佳人用户id
UserInfo userInfo = userInfoApi.queryUserInfo(userId);
BeanUtils.copyProperties(userInfo, todayBestVo);
//设置tags
if (!StringUtils.isEmpty(userInfo.getTags())) {
todayBestVo.setTags(userInfo.getTags().split(","));
}
//设置缘分值
todayBestVo.setFateValue(recommendUser.getScore().longValue());
todayBestVoList.add(todayBestVo);
}
//4.将数据封装返回
BeanUtils.copyProperties(pageResult, voPageResult);//copy分页数据
voPageResult.setItems(todayBestVoList);//将todayBestVoList设置到返回的Vo中
return voPageResult;
}
//构造默认数据
private List<RecommendUser> defaultRecommend() {
String ids = "1,2,3,4,5,6,7,8,9,10";
List<RecommendUser> records = new ArrayList<>();
for (String id : ids.split(",")) {
RecommendUser recommendUser = new RecommendUser();
recommendUser.setUserId(Long.valueOf(id));
recommendUser.setScore(RandomUtils.nextDouble(70, 98));
records.add(recommendUser);
}
return records;
}
/**
* 查看用户详情
* {id}:佳人用户id
*/
public TodayBestVo personalInfo(Long personUserId) {
// a.根据佳人用户id查询userInfo
UserInfo userInfo = userInfoApi.queryUserInfo(personUserId);
// b.调用服务获取缘分值
Double score = recommendUserApi.queryForScore(personUserId, UserHolder.getUserId());
// c.封装vo
TodayBestVo vo = new TodayBestVo();
BeanUtils.copyProperties(userInfo, vo);
if (userInfo != null && !StringUtils.isEmpty(userInfo.getTags())) {
vo.setTags(userInfo.getTags().split(","));
}
vo.setFateValue(score.longValue());//缘分值
return vo;
}
/**
* 查询陌生人问题
* userId:佳人用户id
*/
public String strangerQuestions(Long userId) {
String txt = "约吗?";
Question question = questionApi.queryByUserId(userId);
if (question != null && !StringUtils.isEmpty(question.getTxt())) {
txt = question.getTxt();
}
return txt;
}
/**
* 回复陌生人问题
*/
public void replyStrangerQuestions(Long userId, String reply) {
//a.UserHolder.getuserId()获取当前用户id
Long currentUserId = UserHolder.getUserId();//当前用户id
//b.根据当前登录用户id 查询userInfo 获取昵称
UserInfo userInfo = userInfoApi.queryUserInfo(currentUserId);
String nickname = userInfo.getNickname();
//c.根据佳人用户id查询问题
Question question = questionApi.queryByUserId(userId);
String txt = "约吗?";
if (question != null && !StringUtils.isEmpty(question.getTxt())) {
txt = question.getTxt();
}
//d.将以上数据封装Map 并将Map转为String字符串
Map<String, String> map = new HashMap();
map.put("userId", currentUserId.toString());//当前用户id
map.put("nickname", nickname);//当前用户昵称
map.put("strangerQuestion", txt);//佳人问题
map.put("reply", reply);//当前用户的回复
String message = JSON.toJSONString(map); //将map转为message消息
//e.调用环信云发送消息给userId佳人用户id target:佳人用户id msg:消息内容
huanXinTemplate.sendMsg(userId.toString(), message);
log.debug("用户{}发送消息给用户{},内容是{}", currentUserId, userId, message);
}
/**
* 添加喜欢
*/
public void addLikeUser(Long id) {
Long userId = UserHolder.getUserId();//当前用户Id
UserLike userLike = new UserLike();
userLike.setUserId(userId);
userLike.setLikeUserId(id);
//添加喜欢的用户
userLikeApi.addLikeUser(userLike);
//查询对方是否喜欢我
UserLike user = userLikeApi.findOne(id, userId);
//判断,如果喜欢则成为好友
if (user != null) {
Friend friend = new Friend();
friend.setUserId(userId);
friend.setFriendId(id);
friendApi.saveFriend(friend);
}
}
/**
* 添加黑名单
*/
public void addBlackUser(Long id) {
Long userId = UserHolder.getUserId();//当前用户Id
BlackList user = blackListApi.findOne(userId, id);
if (user == null) {
BlackList blackList = new BlackList();
blackList.setUserId(userId);
blackList.setBlackUserId(id);
blackListApi.addBlackUser(blackList);
}
}
}
|