MongoDB地理位置索引

相信大家一定都知道微信“附近的门店”这个功能,市面上其他软件也有类似的功能,通过获取当前位置来查找附近一定范围内的某样东西。面对这些需求,mongodb为我们提供了地理位置索引。
在mongodb中,地理位置索引的概念是将一些点(其实也不仅仅是点,后面会提到)的位置储存在mongodb中,创建索引后,可以按照位置进行查询。
mongodb地理位置索引分为2d索引与2dsphere索引。前者用于储存和查找平面上的点,后者用于储存和查找球面上的点。下面将为大家详细讲解这两种地理位置索引。

2d索引
创建方式:db.集合名.ensureIndex({key:”2d”})
举个栗子,我们先在数据库中插入几个地点的数据

db.imooc_collection.insert({name:"圆明园",pos:[90,70]})
db.imooc_collection.insert({name:"故宫",pos:[100,80]})
db.imooc_collection.insert({name:"卢浮宫",pos:[90,30]})

这里需要注意的是,表示坐标的pos的值是一个数组,包含两个值,分别代表经度和维度,经度[-180,180],维度[-90,90]。在插入时,如果经度超过范围会会提示错误,而维度却不会,但查询的时候会发生“不可预期的错误”。
那么我们在插入数据并且建立好索引之后,就可以开始查询数据了。查询的方式有三种,分别是near、geoWithin、geoNear
naer查询

db.集合名.find({pos:{$near:[经度,维度]}})

如果我们直接像这样子进行查询,结果会按照离目标坐标的远近输出数据库中存储的100个位置信息,所以,要精确查找距离目标坐标一定范围内的位置,则需要$maxDistance的帮助。所以,我们可以把上面的代码修改为下面这样子

db.集合名.find({pos:{$near:[经度,维度],$maxDistance:10}})

这样,就只显示距离目标坐标半径10以内的位置。
那么,一个关键的问题来了maxDistance中数值的单位是什么?
接下来的一些其他的参数的单位也会涉及到这个问题。这些数值的单位是公里还是米?
正如之前所说,2d索引用于储存和查找平面上的点,虽然其坐标的取值被限制在现实世界中经纬度的取值范围内,但事实上,我们应该理解这些使用2d索引的点其实都在一个平面直角坐标系上。这个坐标系的x轴取值范围为[-180,180],y轴取值范围为[-90,90],所谓的Distancs其实就是按照平面坐标系上两点的距离公式计算出来的。mongodb从3.0.0版本开始支持minDistance
geoWithin查询
该查询方式用于查询某个形状内的点,形状主要有矩形、圆形、多边形三种,分别表示如下
db.集合名.find({pos:{$geoWithin:{$box:[[0,0],[3,3]]}}})
矩形,box的两个值分别代表矩形左上角与右下角的坐标

db.集合名.find({pos:{$geoWithin:{$center:[[0,0],r]}}})
圆形,center的两个值分别代表圆心的坐标与半径

db.集合名.find({pos:{$geoWithin:{$polygon:[[0,0],[3,3],[4,4],……]}}})
矩形,polygon的值代表多边形各个顶点的坐标

geoNear查询
geoNear查询使用runCommand命令进行使用

db.runCommand({
    geoNear:集合名字符串,
    near:坐标数组,
    minDistance:最小距离,可选
    maxDistance:最多距离,可选
    num:限制返回结果的数目
)}

我们来看一个实例
这里写图片描述
在返回结果中的dis字段的值是当前位置与目标位置之间通过两点间距离公式算出来的结果
在两个位置距离相距不是很远的时候,经纬线网可以看出一个平面直角坐标系。但随着距离的增加,地球曲率的影响越来越大,经纬线网就不能再看出平面直角坐标系了。这个时候就要用到2dsphere索引了

2dsphere索引
创建方式:db.集合名.ensureIndex({pos:”2dsphere”})
需要注意的是,在2dsphere索引中,位置的表示方式不再以[经度,维度]来表示,其表示方式叫做GeoJSON
GeoJSON的写法为:{type:”Point/LineString/Polygon”,coordinates:[经度,维度]}
其中type字段表示当前坐标是一个点的坐标还是一条线或者一个多边形的;coordinates字段则表示当前位置的坐标——如果是一个点,那就是该点的经度维度、如果是一条线,则是线起点与终点的坐标、如果是多边形,则是多边形各个顶点的坐标。需要注意的是,使用2dsphere索引的数据中必须有GeoJSON字段,比如:

db.imooc_collection.insert({name:"金字塔",pos:{type:"point",coordinates:[105,41]}})

pos字段就是一个GeoJSON数据。2dsphere的查询方式与2d一样,我们将之前圆明园、故宫、卢浮宫的数据换成GeoJSON形式进行一次查找
这里写图片描述
在这个例子中我们可以看到2dsphere索引的查询必须要设置spherical: true”
这个参数的设置将两个位置之间的距离换算成米(这里有很多博客或者教程认为是换算成了km,之前我也是这样认为的,但经过实践,单位应当是m),具体如何根据经纬度换算距离大家可以自行百度,我给大家推荐一个根据经纬度算距离的在线工具
http://www.storyday.com/wp-content/uploads/2008/09/latlung_dis.html
根据这个工具再来看实例中的距离,整数部分一致,小数部分略有出入,不过还是可以接受。
以上就是我对MongoDB地理位置索引的一些理解,大家尤其需要注意距离的单位。如有出错的地方,请在下方评论区中指出,阿里嘎多。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值