Geospatial Indexingmongodb
MongoDB支持二維空間索引,這是設計時考慮到基於位置的查詢。例如「找到離目標位置最近的N條記錄」。能夠有效地做爲附加條件過濾。json
若是須要使用這種索引,應肯定對象中存儲的字段是子對象或數組,前兩個元素爲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 ] } ui
{ loc : { x : 50 , y : 30 } } this
{ loc : { foo : 50 , y : 30 } } spa
{ loc : { lat : 40.739037, long: 73.992964 } } 設計
Creating the Indexcode
Mongo代碼 orm
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
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. |
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. |
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 } |