Spring data mongodb实现LBS
基本介绍
位置服务(LBS)解决的主要问题是当前位置周围某个范围内的人或场所.
在传统的解决方案,开发人员需要根据复杂的几何运算与大量的SQL语句进行查找,这无疑加大的开发人员的开发难度.
现在我们需要更为方便的解决方案,MongoDB为我们完美解决此类LBS问题.此篇文章也主要使用SpringData,将spring与MongoDB进行整合.
二维地图
MongoDB目前支持二维的地图查询,查询区域包括圆形与矩形,距离单位包括MILES,KILOMETERS,NEUTRAL,下面的示例演示距离单位为NEUTRAL,而实际生产应用中则会用到MILES与KILOMETERS.
MongoDB示例
首先定义一个位置集合,给定a,b,c,d节点.
1 2 3 4 5 6 7 8 |
> db.createCollection("location") { "ok" : 1 } > db.location.save( {_id: "A", position: [0.1, -0.1]} ) > db.location.save( {_id: "B", position: [1.0, 1.0]} ) > db.location.save( {_id: "C", position: [0.5, 0.5]} ) > db.location.save( {_id: "D", position: [-0.5, -0.5]} ) |
接着指定location索引
1 |
db.location.ensureIndex( {position: "2d"} ) |
现在我们可以进行简单的GEO查询
查询point(0,0),半径0.7附近的点
1 2 3 4 |
> db.location.find( {position: { $near: [0,0], $maxDistance: 0.7 } } ) { "_id" : "A", "position" : [ 0.1, -0.1 ] } |
查询point(0,0),半径0.75附近的点
1 2 3 4 5 6 |
> db.location.find( {position: { $near: [0,0], $maxDistance: 0.75 } } ) { "_id" : "A", "position" : [ 0.1, -0.1 ] } { "_id" : "C", "position" : [ 0.5, 0.5 ] } { "_id" : "D", "position" : [ -0.5, -0.5 ] } |
我们可以看到半径不一样,查询出的点也不一样,因为c点坐标为[0.5,0.5],c至圆点的距离根据勾股定理可得出Math.sqrt(0.25 +0.25) ≈ 0.707,所以最大距离0.7时查找不到你要的点.
查询[0.25, 0.25], [1.0,1.0]区域附近的点
1 2 3 4 5 |
> db.location.find( {position: { $within: { $box: [ [0.25, 0.25], [1.0,1.0] ] } } } ) { "_id" : "C", "position" : [ 0.5, 0.5 ] } { "_id" : "B", "position" : [ 1, 1 ] } |
Spring Data示例
spring data为我们封装了mongoDB访问接口与实现,我们可以像使用hibernateTemplate一样使用mongoTemplate.
首先我们需要像hibernate一样定义pojo类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "location") public class Location { @Id private String id; private double[] position; /** getter setter hashcode equals toString ... */ } |
定义Dao,我们先使用最简单的mongoTemplate来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.Box; import org.springframework.data.mongodb.core.geo.Point; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Repository; @Repository public class LocationDao { @Autowired MongoTemplate mongoTemplate; public List<Location> findCircleNear(Point point, double maxDistance) { return mongoTemplate.find( new Query(Criteria.where("position").near(point).maxDistance(maxDistance)), Location.class); } public List<Location> findBoxNear(Point lowerLeft, Point upperRight) { return mongoTemplate.find( new Query(Criteria.where("position").within(new Box(lowerLeft, upperRight))), Location.class); } } |
最后我们写一个test类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
import java.util.Collection; import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.Point; import org.springframework.data.mongodb.core.index.GeospatialIndex; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/applicationContext.xml", "classpath:/application-mongo.xml" }) public class MongoDBTest { @Autowired LocationDao locationDao; @Autowired MongoTemplate template; @Before public void setUp() { // 等同db.location.ensureIndex( {position: "2d"} ) template.indexOps(Location.class).ensureIndex(new GeospatialIndex("position")); // 初始化数据 template.save(new Location("A", 0.1, -0.1)); template.save(new Location("B", 1, 1)); template.save(new Location("C", 0.5, 0.5)); template.save(new Location("D", -0.5, -0.5)); } @Test public void findCircleNearTest() { List<Location> locations = locationDao.findCircleNear(new Point(0, 0), 0.7); print(locations); System.err.println("-----------------------"); locations = locationDao.findCircleNear(new Point(0, 0), 0.75); print(locations); } @Test public void findBoxNearTest() { List<Location> locations = locationDao.findBoxNear(new Point(0.2, 0.2), new Point(1, 1)); print(locations); } public static void print(Collection<Location> locations) { for (Location location : locations) { System.err.println(location); } } } |
大家可以看到运行结果与我们直接在mongoDB上的一样.
MongoRepository
MongoRepository提供了对MongoTemplate的封装与实现,只需要继承MongoRepository接口,填上对应的bean类与ID类型,无需实现里面的方法即可使用,先看代码.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import org.springframework.data.mongodb.core.geo.Box; import org.springframework.data.mongodb.core.geo.Distance; import org.springframework.data.mongodb.core.geo.Point; import org.springframework.data.mongodb.repository.MongoRepository; public interface LocationRepository extends MongoRepository<Location, String> { List<Location> findByPositionNear(Point p, Distance d); List<Location> findByPositionWithin(Box b); } |
然后在test类中引用此类即可,MongoRepository实现了最基本的增删改查的功能,要想增加额外的查询方法,可以按照以下规则定义接口的方法.
自定义查询方法,格式为findBy+字段名+方法名,方法传进的参数即字段的值,此外还支持分页查询,通过传进一个Pageable对象会返回Page集合.
原理相信大家也很清楚,即aop,细节就不说拉.
小提示
near与within方法区别,near方法查询后会对结果集对distance进行排序且有大小限制,而within是无序的也无大小限制.
如果大家有新发现,也可回帖,我会及时补充.
转载于:https://my.oschina.net/u/2307059/blog/749997
Spring data mongodb实现LBS相关推荐
- mongodb数据库java接口,MongoDB —— 使用Spring Data MongoDB操作数据库
我们使用Spring Data MongoDB可以方便的在Spring boot项目中操作MongoDB 文档地址:https://docs.spring.io/spring-boot/docs/2. ...
- 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南
1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...
- Spring Data MongoDB教程
在当今世界,尽快启动并运行应用程序非常重要. 该应用程序还应该易于开发和维护. Spring是这样的框架,它提供了与许多不同框架的集成的简便性,这使得使用Spring开发应用程序变得容易. 一种这样的 ...
- 数据聚合Spring Data MongoDB:嵌套结果
1引言 在上一篇文章中,我们构建了聚合管道的基本示例. 如果您需要有关如何创建项目和配置应用程序的更多详细信息,也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚 ...
- orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序
orderby排序慢 这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值 ...
- Spring Data MongoDB级联保存在DBRef对象上
默认情况下, Spring Data MongoDB不支持对带有@DBRef注释的引用对象的级联操作,如引用所述 : 映射框架不处理级联保存 . 如果更改了Person对象引用的Account对象,则 ...
- Spring Data MongoDB中的审核实体
Spring Data MongoDB 1.2.0静默引入了新功能:支持基本审核 . 因为您不会在本文的官方参考中找到太多有关它的信息,所以我将展示它带来的好处,如何配置Spring以进行审计以及如何 ...
- 使用NoSQLUnit测试Spring Data MongoDB应用程序
Spring Data MongoDB是Spring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用MongoDB作为数据库的应用程序. 要使用NoSQLUnit为Spring ...
- 使用@OrderBy对Spring Data MongoDB集合进行排序
这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值关联的元素的顺序. 在 ...
最新文章
- php中的全局变量$_REQUEST
- 汇编loop指令及用法解释
- huffman python_Python huffman包_程序模块 - PyPI - Python中文网
- 如何申请注销腾讯视频账号
- 【火炉炼AI】机器学习032-用户之间相似度的计算
- 微信公众号在调用扫一扫功能时,一维码(条形码)在直接返回结果时会在结果前带上EAN_8, EAN_13, CODE_25, CODE_39, CODE_128, UPC_A, UPC_E...
- 被亚马逊下架含18650锂电池产品
- cad批量逐个填充lisp,效率提高之CAD如何自动批量导出文本
- 草根创业,我劝你抓住网络培训的机会!
- 论文解读笔记:基于深度学习的行为分析综述
- WIN32 API GetLastError()返回值含义列表
- Canvas线条花环
- C++ Primer Plus (第六版)编程练习记录(chapter8 函数探幽)
- idea中好用的git shelve changes和stash changes
- 关于测绘专业软件时的一些感悟
- 好用的前端组件-颜色选择器
- Swoft 系列教程:(2)认证服务及组件
- SystemUI模块总结
- C++中endl、“\n”和‘\n’的区别
- Gurobi9.0.3安装
热门文章
- php转调页面,怎样练到转调弹奏信手捏来,太实用
- 各纬度气候分布图_气候气压带图_世界气候气压带风带分布图要图(需要表识纬度)-4d影院专题信息栏目...
- 哈萨克斯坦大型“零元购”抓捕现场
- 笔记1-----校园网进知网步骤
- 计算机英语boot,电脑开不了机显示英文boottmgr
- python excel 饼图 简书_Python可视化29_matplotlib-饼图(pie)
- 学习opencv:PS滤镜—曝光过度
- 江在川上曰:webpack前端工程化
- 新浪服务器mysql_php新浪云链接mysql与storage
- catia刨面命令_Catia查看装配体剖面的操作方法