2dsphere允许使用GeoJSON格式的数据指定点,线和多边形。可以按照坐标轴:经度,纬度 的方式把位置数据存储为GeoJSON对象。GeoJSON的坐标参考系使用是 WGS84 数据。 如果选择球形表面来计算,可以选择把位置数据存储为如下两种格式之一:
对GeoJSON的查询总是基于球形表面。GeoJSON的默认坐标参考系使用的是WGS84 数据。
2.4 新版功能: 在版本2.4新引入了对GeoJSON的存储和查询支持。在版本2.4以前,所有的地理数据使用坐标对的形式。
在 2.6 版更改: 支持更多GeoJSON类型:多点, 多线段, MultiPolygon, 几何体集合。
MongoDB支持如下GeoJSON对象:
MongoDB支持对使用 2dsphere 索引的 legacy coordinate pairs (普通坐标对)数据进行球面计算,方式是把数据转换成GeoJSON Point类型。
点可以用形如[longitude,latitude](经纬度)的两个元素的数组表示:
{
"name":"BeiJin",
"loc":{
"type":"Point",
"coordinates":[50,2]
}
}
线可以由点组成的数组表示
{
"name":"BeiJin",
"loc":{
"type":"Line",
"coordinates":[[0,1],[0,2],[0,3]]
}
}
多边形的也是由点组成的数组表示的
{
"name":"BeiJin",
"loc":{
"type":"Polygon",
"coordinates":[[0,1],[0,2],[0,3]]
}
}
在ensureIndex中使用2psphere选项就可以创建一个地理空间索引
db.word.ensureIndex({"loc":"2dsphere"})
注意:"loc"字段的名字是任意的,但是其中的子对象是由GeoJSON指定的,不能改变
可以使用多种不同类型的地理空间查询,交集(intersection),包含(within)以及接近(nearness)。查询的时候将要查找的内容指定为形如{"$geometry":geoJsonDesc}的GeoJSON对象
建立word集合来存放地点
db.word.insert([{"name":"华山","loc":{"type":"Point","coordinates":[-98,45]}},{"name":"泰山","loc":{"type":"Point","coordinates":[3,1]}},{"name":"衡山","loc":{"type":"Point","coordinates":[-88,40]}}])
建立索引
db.word.ensureIndex({loc:"2dsphere"})
当然也可以建立组合索引
db.word.ensureIndex({loc:"2dsphere",name:1})
cqsm>db.word.find( { loc :
... { $geoWithin :
... { $geometry :
... { type : "Polygon" ,
... coordinates : [ [
... [ 0 , 0 ] ,
... [ 3 , 6 ] ,
... [ 6 , 1 ] ,
... [ 0 , 0 ]
... ] ]
... } } } } )
{ "_id" : ObjectId("5dde41c48ead21d246cc04ae"), "name" : "泰山", "loc" : { "type" : "Point", "coordinates" : [ 3, 1 ] } }
注意:定义的多边形一定要首尾相连,注意coordinates中数组的顺序,而且coordinates后一定要是数组
向word集合中插入一个图形(最好是四个点,首尾相同)
db.word.insert({"name":"黄山","loc":{ type : "Polygon" ,
coordinates : [ [
[ 3 , 3 ] ,
[ 3.2 , 3.2 ] ,
[ 3.2 , 3 ] ,
[ 3 , 3 ]
] ]
}})
var name={type : "Polygon" ,coordinates : [ [
[ 3 , 3 ] ,
[ 3.2 , 3.2 ] ,
[ 3.2 , 3 ] ,
[ 3 , 3 ]
] ]}
使用"$geoIntersects"操作符找出与查询位置相交的文档
cqsm>db.word.find({loc:{"$geoIntersects":{"$geometry":name}}}).pretty()
{
"_id" : ObjectId("5ddf3065d01148e24144f20c"),
"name" : "黄山",
"loc" : {
"type" : "Polygon",
"coordinates" : [
[
[
3,
3
],
[
3.2,
3.2
],
[
3.2,
3
],
[
3,
3
]
]
]
}
}
{
"_id" : ObjectId("5ddf29fdd01148e24144f20a"),
"name" : "黄山",
"loc" : {
"type" : "Polygon",
"coordinates" : [
[
[
0,
0
],
[
3,
6
],
[
6,
1
],
[
0,
0
]
]
]
}
}
db.word.insert({"loc":{ type : "Polygon" ,
coordinates : [
[ 3 , 3 ] ,
[ 3.2 , 3.2 ] ,
[ 3.2 , 3 ] ,
[ 3 , 3 ]
]
}})
db.word.find( { loc :
{ $near :
{ $geometry :
{ type : "Point" ,
coordinates : [ <longitude> , <latitude> ] } ,
$maxDistance : <distance in meters>
} } } )
指定圆心和半径,[-88, 30] 为经纬度, 10为半径
查询圆形内的值
db.word.find( { loc :
{ $geoWithin :
{ $centerSphere :
[ [ -88 , 30 ] , 10 ]
} } } )
查询附近,结果集会按照距离排序
db.word.find(
{location:{$near:{$geometry:{type:"Point",coordinates:[120.223004,30.215452]},$maxDistance:500}}})
2d索引适用于扁平表面,而不是球体表面。2d索引只能对点进行索引,可以保存一个由点组成的数组,但是它只会被保存为由点组成的数组而不是当成线。
db.word.ensureIndex({"title":"2d"})
默认情况下地理空间索引是假设值在-180到180,可以根据需要在ensureIndex中设置更大范围的索引边界值。
db.word.ensureIndex({"title":"2d"},{"min":-1000,"max":1000}) //不能修改已经建立的索引字段边界值
使用2d索引进行索引,不必带有$geometry子对象,可以直接指定坐标
db.word.find({"title":{$near:[18,19]}})
db.word.find({"title":{$near:[18,19]}}).limit(3) //只返回三个
可以使用$winthin查询出某个形状范围内的所有文档
db.word.find({"title":{"$within":{"$box":[[10,20],[15,30]]}}}) //box接受两个元素的数组,一个指定左下角的坐标,一个指定右上角的坐标
db.word.find({"title":{"$within":{"$centr":[[10,20],5]}}}) //指定圆心和半径
db.word.find({"title":{"$within":{"$polygon":[[10,20],[15,30],[23,22],[10,20]]}}}) //使用多个点的数组表示多边形