基本介绍

位置服务(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相关推荐

  1. mongodb数据库java接口,MongoDB —— 使用Spring Data MongoDB操作数据库

    我们使用Spring Data MongoDB可以方便的在Spring boot项目中操作MongoDB 文档地址:https://docs.spring.io/spring-boot/docs/2. ...

  2. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  3. Spring Data MongoDB教程

    在当今世界,尽快启动并运行应用程序非常重要. 该应用程序还应该易于开发和维护. Spring是这样的框架,它提供了与许多不同框架的集成的简便性,这使得使用Spring开发应用程序变得容易. 一种这样的 ...

  4. 数据聚合Spring Data MongoDB:嵌套结果

    1引言 在上一篇文章中,我们构建了聚合管道的基本示例. 如果您需要有关如何创建项目和配置应用程序的更多详细信息,也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚 ...

  5. orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序

    orderby排序慢 这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值 ...

  6. Spring Data MongoDB级联保存在DBRef对象上

    默认情况下, Spring Data MongoDB不支持对带有@DBRef注释的引用对象的级联操作,如引用所述 : 映射框架不处理级联保存 . 如果更改了Person对象引用的Account对象,则 ...

  7. Spring Data MongoDB中的审核实体

    Spring Data MongoDB 1.2.0静默引入了新功能:支持基本审核 . 因为您不会在本文的官方参考中找到太多有关它的信息,所以我将展示它带来的好处,如何配置Spring以进行审计以及如何 ...

  8. 使用NoSQLUnit测试Spring Data MongoDB应用程序

    Spring Data MongoDB是Spring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用MongoDB作为数据库的应用程序. 要使用NoSQLUnit为Spring ...

  9. 使用@OrderBy对Spring Data MongoDB集合进行排序

    这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值关联的元素的顺序. 在 ...

最新文章

  1. php中的全局变量$_REQUEST
  2. 汇编loop指令及用法解释
  3. huffman python_Python huffman包_程序模块 - PyPI - Python中文网
  4. 如何申请注销腾讯视频账号
  5. 【火炉炼AI】机器学习032-用户之间相似度的计算
  6. 微信公众号在调用扫一扫功能时,一维码(条形码)在直接返回结果时会在结果前带上EAN_8, EAN_13, CODE_25, CODE_39, CODE_128, UPC_A, UPC_E...
  7. 被亚马逊下架含18650锂电池产品
  8. cad批量逐个填充lisp,效率提高之CAD如何自动批量导出文本
  9. 草根创业,我劝你抓住网络培训的机会!
  10. 论文解读笔记:基于深度学习的行为分析综述
  11. WIN32 API GetLastError()返回值含义列表
  12. Canvas线条花环
  13. C++ Primer Plus (第六版)编程练习记录(chapter8 函数探幽)
  14. idea中好用的git shelve changes和stash changes
  15. 关于测绘专业软件时的一些感悟
  16. 好用的前端组件-颜色选择器
  17. Swoft 系列教程:(2)认证服务及组件
  18. SystemUI模块总结
  19. C++中endl、“\n”和‘\n’的区别
  20. Gurobi9.0.3安装

热门文章

  1. php转调页面,怎样练到转调弹奏信手捏来,太实用
  2. 各纬度气候分布图_气候气压带图_世界气候气压带风带分布图要图(需要表识纬度)-4d影院专题信息栏目...
  3. 哈萨克斯坦大型“零元购”抓捕现场
  4. 笔记1-----校园网进知网步骤
  5. 计算机英语boot,电脑开不了机显示英文boottmgr
  6. python excel 饼图 简书_Python可视化29_matplotlib-饼图(pie)
  7. 学习opencv:PS滤镜—曝光过度
  8. 江在川上曰:webpack前端工程化
  9. 新浪服务器mysql_php新浪云链接mysql与storage
  10. catia刨面命令_Catia查看装配体剖面的操作方法