MongoDB--地理空间索引

MongoDB–地理空间索引

文章目录

    • MongoDB--地理空间索引
      • 一:2dsphere索引
        • 1. 简介
          • 1. GeoJSON对象
          • 2. 普通坐标对
        • 2. 点,线,图形的表示
        • 3. 地理空间查询的类型
          • 3.1 在指定范围内的点
          • 3.2 与指定位置相交的位置的文档
          • 3.3 查询附件的位置
          • 3.4 查询圆形内的值
        • 4. 注意
      • 二:2d索引

MongoDB支持几种类型的地理空间索引,其中最常用的就是2dsphere索引(用于地球表面类型的地图)和2d索引(用于平面地图和时间连续的数据)

一:2dsphere索引

1. 简介

2dsphere允许使用GeoJSON格式的数据指定点,线和多边形。可以按照坐标轴:经度,纬度 的方式把位置数据存储为GeoJSON对象。GeoJSON的坐标参考系使用是 WGS84 数据。 如果选择球形表面来计算,可以选择把位置数据存储为如下两种格式之一:

1. GeoJSON对象

对GeoJSON的查询总是基于球形表面。GeoJSON的默认坐标参考系使用的是WGS84 数据。

2.4 新版功能: 在版本2.4新引入了对GeoJSON的存储和查询支持。在版本2.4以前,所有的地理数据使用坐标对的形式。

在 2.6 版更改: 支持更多GeoJSON类型:多点, 多线段, MultiPolygon, 几何体集合。

MongoDB支持如下GeoJSON对象:

  • 单点
  • 线段
  • 多边形
  • 多点
  • 多线段
  • MultiPolygon
  • 几何体集合
2. 普通坐标对

MongoDB支持对使用 2dsphere 索引的 legacy coordinate pairs (普通坐标对)数据进行球面计算,方式是把数据转换成GeoJSON Point类型。

2. 点,线,图形的表示

点可以用形如[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指定的,不能改变

3. 地理空间查询的类型

可以使用多种不同类型的地理空间查询,交集(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})

3.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后一定要是数组

3.2 与指定位置相交的位置的文档

向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 ]
                                       ] 
                }})   
3.3 查询附件的位置
db.word.find( { loc :
                        { $near :
                          { $geometry :
                             { type : "Point" ,
                               coordinates : [ <longitude> , <latitude> ] } ,
                            $maxDistance : <distance in meters>
                     } } } )
3.4 查询圆形内的值

指定圆心和半径,[-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}}})

4. 注意

  • GEOJson数据中,coordinates数组要闭环,"loc"字段的名字是任意的,但是其中的子对象是由GeoJSON指定的,不能改变
  • $geoIntersects和within不需要地理空间索引就可以使用,但是near需要使用索引
  • 建议在地理位置的字段上建立索引,可以显著的提高查询速度

二:2d索引

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]]}}}) //使用多个点的数组表示多边形

你可能感兴趣的:(MongoDB)