使用MongoDB地理空间索引踩的一些小坑

Posted by kyle on December 31, 2017

MongoDB的地理空间索引主要是用来解决“获取空间中(可以是2D平面空间,也可以是球面空间)某一基准点的邻近点”的问题,其核心算法是基于GeoHash的。

坐标

既然要计算空间上的邻近点,那么当然需要在相关的集合中加入特定的字段用以标明坐标。

MongoDB支持两种坐标表示形式,

一种是Double数组,形如:

[ -73.9667, 40.78 ]、[0, 80]

在2D平面中使用时,约定格式为[x, y],

在球面空间使用时,约定格式为[longitude, latitude]

另一种是GeoJSON,简单说来,就是JSON格式,只不过对它里面的字段做了限定,它的格式是这样子的:

{

type: “Point”,

coordinates: [ 40, 5 ]

}

这里的type,指的是当前所代表的几何体类型,

主要有3种独立类型:

Point、LineString、Polygon

和4种集合类型:

MultiPoint、MultiLineString、MultiPolygon、GeometryCollection

对于坐标来说,当然就只能是Point了。

2d、2dsphere

在MongoDB中,想要运用它的地理空间检索,必须给相应字段建立索引,主要有2d、2dsphere这两种索引,

建立的语法分别为:

db.集合名.createIndex({“字段1”: “2d”}) db.集合名.createIndex({“字段2”: “2dsphere”})

这样就给字段1增加了2d索引,给字段2增加了2dsphere索引

$near、$nearSphere

$near、$nearSphere是MongoDB中用来获取某一基准点的邻近点、并且由近至远排好序的操作。他们都支持对2d索引和2dsphere索引的操作,但有如下需要注意的点:

●$near检索时,若标识坐标的字段为2d索引,它传入的基准点的格式必须是Double数组型的;若标识坐标的字段为2dsphere索引,传入的基准点的格式则必须为GeoJSON型。

●对于$nearSphere,若作用在2d索引上,则要求该2d索引必须是建立在集合中GeoJSON型数据的coordinates字段上,且传入的基准点的格式必须是Double数组型的;若作用在2dsphere索引上,则对基准点的格式无要求。

●传入的基准点格式为Double数组时,$minDistance、$maxDistance的计算都是以弧度为单位的;

传入的基准点格式为GeoJSON时,计算是以距离:米为单位的。

返回距离

$near、$nearSphere虽然能够检索出邻近点,并且由近至远排好序,但是这两个操作是不返回距离的。

返回距离需要用到聚合检索中的$geoNear,其使用方法为:

db.集合名.aggregate([{ $geoNear: { near: { type: “Point”, coordinates: [ -73.99279 , 40.719296 ] }, distanceField: “dist.calculated”, maxDistance: 2, query: { type: “public” }, includeLocs: “dist.location”, num: 5, spherical: true } }])

其中,distanceField用来声明计算出的距离所在的字段。

更多详细可以查看MongoDB官网: https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/