1.3、喜欢的dubbo服务
用户的喜欢与不喜欢列表需要保存在redis中,为了防止redis中的数据丢失,同时需要将数据保存到mongodb进行持久化保存。
1.3.1、定义接口
1. package com.tanhua.dubbo.api; 2. 3. public interface UserLikeApi { 4. 5. //保存或者更新 6. Boolean saveOrUpdate(Long userId, Long likeUserId, boolean isLike); 7. }
1.3.2、编写实现
1. @DubboService 2. public class UserLikeApiImpl implements UserLikeApi{ 3. 4. @Autowired 5. private MongoTemplate mongoTemplate; 6. 7. @Override 8. public Boolean saveOrUpdate(Long userId, Long likeUserId, boolean isLike) { 9. try { 10. //1、查询数据 11. Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").is(likeUserId)); 12. UserLike userLike = mongoTemplate.findOne(query, UserLike.class); 13. //2、如果不存在,保存 14. if(userLike == null) { 15. userLike = new UserLike(); 16. userLike.setUserId(userId); 17. userLike.setLikeUserId(likeUserId); 18. userLike.setCreated(System.currentTimeMillis()); 19. userLike.setUpdated(System.currentTimeMillis()); 20. userLike.setIsLike(isLike); 21. mongoTemplate.save(userLike); 22. }else { 23. //3、更新 24. Update update = Update.update("isLike", isLike) 25. .set("updated",System.currentTimeMillis()); 26. mongoTemplate.updateFirst(query,update,UserLike.class); 27. } 28. return true; 29. } catch (Exception e) { 30. e.printStackTrace(); 31. return false; 32. } 33. } 34. }
1.4、左滑右滑
左滑:“不喜欢”,右滑:“喜欢”,如果双方喜欢,那么就会成为好友。
1.4.1、TanHuaController
1. /** 2. * 喜欢 3. */ 4. @GetMapping("{id}/love") 5. public ResponseEntity<Void> likeUser(@PathVariable("id") Long likeUserId) { 6. this.tanhuaService.likeUser(likeUserId); 7. return ResponseEntity.ok(null); 8. } 9. 10. /** 11. * 不喜欢 12. */ 13. @GetMapping("{id}/unlove") 14. public ResponseEntity<Void> notLikeUser(@PathVariable("id") Long likeUserId) { 15. this.tanhuaService.notLikeUser(likeUserId); 16. return ResponseEntity.ok(null); 17. }
1.4.2、TanHuaService
1. @Autowired 2. private MessagesService messagesService; 3. 4. //探花喜欢 106 - 2 5. public void likeUser(Long likeUserId) { 6. //1、调用API,保存喜欢数据(保存到MongoDB中) 7. Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(),likeUserId,true); 8. if(!save) { 9. //失败 10. throw new BusinessException(ErrorResult.error()); 11. } 12. //2、操作redis,写入喜欢的数据,删除不喜欢的数据 (喜欢的集合,不喜欢的集合) 13. redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString()); 14. redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString()); 15. //3、判断是否双向喜欢 16. if(isLike(likeUserId,UserHolder.getUserId())) { 17. //4、添加好友 18. messagesService.contacts(likeUserId); 19. } 20. } 21. 22. public Boolean isLike(Long userId,Long likeUserId) { 23. String key = Constants.USER_LIKE_KEY+userId; 24. return redisTemplate.opsForSet().isMember(key,likeUserId.toString()); 25. } 26. 27. //不喜欢 28. public void notLikeUser(Long likeUserId) { 29. //1、调用API,保存喜欢数据(保存到MongoDB中) 30. Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(),likeUserId,false); 31. if(!save) { 32. //失败 33. throw new BusinessException(ErrorResult.error()); 34. } 35. //2、操作redis,写入喜欢的数据,删除不喜欢的数据 (喜欢的集合,不喜欢的集合) 36. redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString()); 37. redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString()); 38. //3、判断是否双向喜欢,删除好友(各位自行实现) 39. }
1.4.3、测试
user_like表,可以看到已经相互喜欢了:
tanhua_users表,可以看到相互是好友了:
环信平台:
2、MongoDB地理位置检索
MongoDB 支持对地理空间数据的查询操作。
2.1、地理位置索引
地理位置查询,必须创建索引才可以能查询,目前有两种索引。
2d :
使用2d index 能够将数据作为二维平面上的点存储起来,在MongoDB 2.4以前使用2。
2dsphere:
2dsphere
索引支持查询在一个类地球的球面上进行几何计算,以GeoJSON对象或者普通坐标对的方式存储数据。
MongoDB内部支持多种GeoJson对象类型:
Point
最基础的坐标点,指定纬度和经度坐标,首先列出经度,然后列出 纬度:
- 有效的经度值介于
-180
和之间180
,两者都包括在内。 - 有效的纬度值介于
-90
和之间90
,两者都包括在内。
{ type: "Point", coordinates: [ 40, 5 ] }
LineString
{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }
Polygon
1. { 2. type: "Polygon", 3. coordinates: [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ] ] 4. }
2.2、案例
查询附近并按照距离返回
查询附近
查询当前坐标附近的目标
1. @Test 2. public void testNear() { 3. //构造坐标点 4. GeoJsonPoint point = new GeoJsonPoint(116.404, 39.915); 5. //构造半径 6. Distance distanceObj = new Distance(1, Metrics.KILOMETERS); 7. //画了一个圆圈 8. Circle circle = new Circle(point, distanceObj); 9. //构造query对象 10. Query query = Query.query(Criteria.where("location").withinSphere(circle)); 11. //省略其他内容 12. List<Places> list = mongoTemplate.find(query, Places.class); 13. list.forEach(System.out::println); 14. }
查询并获取距离
我们假设需要以当前坐标为原点,查询附近指定范围内的餐厅,并直接显示距离
1. //查询附近且获取间距 2. @Test 3. public void testNear1() { 4. //1、构造中心点(圆点) 5. GeoJsonPoint point = new GeoJsonPoint(116.404, 39.915); 6. //2、构建NearQuery对象 7. NearQuery query = NearQuery.near(point, Metrics.KILOMETERS).maxDistance(1, Metrics.KILOMETERS); 8. //3、调用mongoTemplate的geoNear方法查询 9. GeoResults<Places> results = mongoTemplate.geoNear(query, Places.class); 10. //4、解析GeoResult对象,获取距离和数据 11. for (GeoResult<Places> result : results) { 12. Places places = result.getContent(); 13. double value = result.getDistance().getValue(); 14. System.out.println(places+"---距离:"+value + "km"); 15. } 16. }
3、上报地理位置
当客户端检测用户的地理位置,当变化大于500米时或每隔5分钟,向服务端上报地理位置。
用户的地理位置存储到MongoDB中,如下: