Geospatial Indexing
MongoDB支持二维空间索引,这是设计时考虑到基于位置的查询。例如“找到离目标位置最近的N条记录”。可以有效地作为附加条件过滤。
如果需要使用这种索引,应确定对象中存储的字段是子对象或数组,前两个元素为X,Y坐标(或者Y,X坐标,保持一致即可。it might be advisible to use order-preserving dictionaries/hashes in your client code, to ensure consistency),一些例子:
Mongo代码
{ loc : [ 50 , 30 ] }
{ loc : { x : 50 , y : 30 } }
{ loc : { foo : 50 , y : 30 } }
{ loc : { lat : 40.739037, long: 73.992964 } }
Creating the Index
Mongo代码
db.places.ensureIndex( { loc : "2d" } ) //应该是固定格式
默认的,Mongo假设你索引的是经度/维度,因此配置了一个从-180到180的取值范围,如果你想索引更多,可以指定该参数:
Mongo代码
db.places.ensureIndex( { loc : "2d" } , { min : -500 , max : 500 } )
上面的代码将衡量索引保证存入的值在-500到500的范围之内。一般来说geo索引仅限于正方形以内且不包括边界以以外的范围,不能再边界上插入值,比如使用上面的代码,点(-500,-500)是不能被插入的。
目前为止,每个Collection只能建立一个geo索引
Querying
该索引可以被用来精确匹配:
Mongo代码
db.places.find( { loc : [50,50] } )
对于geo索引来说,更重要的是一个查询可以找到目标点附近的点,不必要精确匹配。
Mongo代码
db.places.find( { loc : { $near : [50,50] } } )
上面的一句将按离目标点(50,50)距离最近的100个点(距离倒序排列),如果想指定返回的结果个数,可以使用limit()函数,若不指定,默认是返回100个。
Mongo代码
db.places.find( { loc : { $near : [50,50] } } ).limit(20)
Compound Indexes
Mongo空间索引可选的支持第二字段索引.如果想用坐标和其他属性同事作为条件查询,把这个属性也一同索引,其他属性带注释性的加入索引中可使过滤更快。
Mongo代码
db.places.ensureIndex( { location : "2d" , category : 1 } );
db.places.find( { location : { $near : [50,50] }, category : 'coffee' } );
geoNear Command
虽然find()语法为查询的首选,Mongo也提供来了 geoNear 命令来执行相似的函数。geoNear命令有一个额外的好处是结果中返回距离目标点的距离,以及一些利于排除故障的信息。
Mongo代码
> db.runCommand( { geoNear : "places" , near : [50,50], num : 10 } );
> db.runCommand({geoNear:"asdf", near:[50,50]})
{
"ns" : "test.places",
"near" : "1100110000001111110000001111110000001111110000001111",
"results" : [
{
"dis" : 69.29646421910687,
"obj" : {
"_id" : ObjectId("4b8bd6b93b83c574d8760280"),
"y" : [
1,
1
],
"category" : "Coffee"
}
},
{
"dis" : 69.29646421910687,
"obj" : {
"_id" : ObjectId("4b8bd6b03b83c574d876027f"),
"y" : [
1,
1
]
}
}
],
"stats" : {
"time" : 0,
"btreelocs" : 1,
"btreelocs" : 1,
"nscanned" : 2,
"nscanned" : 2,
"objectsLoaded" : 2,
"objectsLoaded" : 2,
"avgDistance" : 69.29646421910687
},
"ok" : 1
}
上面的命令将返回10条距离点(50,50)最近的记录,loc字段由该collection的空间索引自动检测后决定。
如果你想添加一条过滤条件,可以这样:
Mongo代码
> db.runCommand( { geoNear : "places" , near : [ 50 , 50 ], num : 10,
... query : { type : "museum" } } );
Bounds Queries
v1.3.4版本以上
$within 参数可以代替$near来查找一个形状之内结果。同时,也支持$box(矩形)和$center(圆环)
想要查找一个一个矩形之内所有的点,必须制定该矩形的左下角和右上角坐标:
Mongo代码
> box = [[40, 40], [60, 60]]
> db.places.find({"loc" : {"$within" : {"$box" : box}}})
更多信息请参考
http://www.mongodb.org/display/DOCS/Geospatial+Indexing
Geospatial Query Operators
Operators¶
Query Selectors
Name | Description |
---|---|
$geoWithin | Selects geometries within a bounding GeoJSON geometry. |
$geoIntersects | Selects geometries that intersect with a GeoJSON geometry. |
$near | Returns geospatial objects in proximity to a point. |
$nearSphere | Returns geospatial objects in proximity to a point on a sphere. |
Geometry Specifiers
Name | Description |
---|---|
$geometry | Specifies a geometry in GeoJSON format to geospatial query operators. |
$maxDistance | Specifies a distance to limit the results of $near and $nearSphere queries. |
$center | Specifies a circle using legacy coordinate pairs to $geoWithin queries when using planar geometry. |
$centerSphere | Specifies a circle using either legacy coordinate pairs or GeoJSON format for $geoWithin queries when using spherical geometry. |
$box | Specifies a rectangular box using legacy coordinate pairs for $geoWithin queries. |
$polygon | Specifies a polygon to using legacy coordinate pairs for $geoWithin queries. |
$uniqueDocs | Modifies a $geoWithin and $near queries to ensure that even if a document matches the query multiple times, the query returns the document once. |
Geospatial Query Compatibility
While numerous combinations of query operators are possible, the following table shows the recommended operators for different types of queries. The table uses the $geoWithin, $geoIntersects and $near operators.
Query Document | Geometry of the Query Condition | Surface Type for Query Calculation | Units for Query Calculation | Supported by this Index |
---|---|---|---|---|
Returns points, lines and polygons | ||||
{ $geoWithin : {
$geometry : <GeoJSON Polygon>
} }
|
polygon | sphere | meters | 2dsphere |
{ $geoIntersects : {
$geometry : <GeoJSON>
} }
|
point, line or polygon | sphere | meters | 2dsphere |
{ $near : {
$geometry : <GeoJSON Point>,
$maxDistance : d
} }
|
point | sphere | meters | 2dsphere The index is required. |
Returns points only | ||||
{ $geoWithin : {
$box : [[x1, y1], [x2, y2]]
} }
|
rectangle | flat | flat units | 2d |
{ $geoWithin : {
$polygon : [[x1, y1],
[x1, y2],
[x2, y2],
[x2, y1]]
} }
|
polygon | flat | flat units | 2d |
{ $geoWithin : {
$center : [[x1, y1], r],
} }
|
circular region | flat | flat units | 2d |
{ $geoWithin : {
$centerSphere :
[[x, y], radius]
} }
|
circular region | sphere | radians | 2d 2dsphere |
{ $near : [x1, y1],
$maxDistance : d
}
|