MongoDB系列五(地理空间索引与查询).

一、经纬度表示方式

MongoDB 中对经纬度的存储有着自己的一套规范(主要是为了可以在该字段上建立地理空间索引)。包括两种方式,分别是 Legacy Coordinate Pairs (这个词实在不知道怎么翻译...) 和  GeoJSON 。

  • Legacy Coordinate Pairs

Legacy Coordinate Pairs 又有两种方式可以存储经纬度,可以使用数组(首选)或嵌入式文档。

数组:

<field>: [<longitude>, <latitude> ]

嵌入式文档:

<field>: { <field1>: <longitude>, <field2>: <latitude> }

tips:有效经度值介于-180和180之间。有效纬度值介于-90和90之间。

  • GeoJSON

GeoJson 比 Legacy Coordinate Pairs 要强大的多,Legacy Coordinate Pairs 仅仅用来保存一个经纬度,而 GeoJson 可以用来指定点、线和多边形。

点可以用形如[longitude, latitude]([经度,纬度])的两个元素的数组表示:

{
"geometry": {
        "type": "Point",
        "coordinates": [125.6, 10.1]
   }
}

线可以用一个由点组成的数组来表示:

{
"geometry": {
        "type": "LineString",
         "coordinates": [[125.6, 10.1],[125.6,10.2],[125.6,10.3]]
   }
}

多边形的表示方式与线一样(都是一个由点组成的数组),但是"type"不同:

{
"geometry": {
        "type": "Polygon",
         "coordinates": [[125.6, 10.1],[125.5,10.2],[125.7,10.3]]
  }
}

type 除了 Point(点)、LineString(线)、Polygon(多边形),还有 MultiPoint(多点)、MultiLineString(多个线) 和  MultiPolygon(多个多边形)。

"geometry"字段的名字可以是任意的,但是其中的子对象是由GeoJSON指定的,不能改变。

二、地理空间索引

  • 2dsphere索引

2dsphere索引用于地球表面类型的地图,允许使用在 Legacy Coordinate Pairs 保存的经纬度字段上和使用GeoJSON格式保存的点、线和多边形字段上。

  db.world.ensureIndex({"geometry" : "2dsphere"})
  • 2d索引

对于非球面地图(游戏地图、时间连续的数据等),可以使用"2d"索引代替"2dsphere"。

2d 索引 仅允许使用在 Legacy Coordinate Pairs 保存的经纬度字段上。

  db.world.ensureIndex({"geometry" : "2d"})
  • 区别:

2dsphere索引只支持球形查询(即球面上几何图形的查询)。

2d索引支持平面查询(即在平面上几何图形的查询)和一些球形查询。虽然2d索引支持一些球形查询,但是对这些球形查询使用2d索引可能会导致错误,例如极点附近会出现大量的扭曲变形。
2d索引只能对点进行索引。可以保存一个由点组成的数组,但是它只会被保存为由点组成的数组,不会被当成线。特别是对于"$geoWithin"查询来说,这是一项重要的区别。如果将街道保存为由点组成的数组,那么如果其中的某个点位于给定的形状之内,这个文档就会与$geoWithin相匹配。但是,由这些点组成的线并不一定完全包含在这个形状之内。

三、地理空间查询

可以使用多种不同类型的地理空间查询:交集(intersection)、包含(within)以及接近(nearness)。

  • $geoIntersects

定义:指出与查询位置相交的文档。

支持的索引:2dsphere

几何操作符:

    1. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形)
  • $geoWithin

定义:指出完全包含在某个区域的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $box(仅支持 2d 索引,查询出矩形范围内的所有文档)
  2. $center(仅支持 2d 索引,查询出圆形范围内的所有文档)
  3. $polygon (仅支持 2d 索引,查询出多边形范围内的所有文档)
  4. $centerSphere(支持 2d 索引和 2dsphere 索引,查询出球面圆形范围内的所有文档)
  5. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形)
  • $near

定义:指出与查询位置从最近到最远的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查询结果的最大距离)
  2. $minDistance (仅支持 2dsphere 索引,指定查询结果的最小距离)
  3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点)
  • $nearSphere

定义:使用球面几何计算近球面的距离,指出与查询位置从最近到最远的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查询结果的最大距离)
  2. $minDistance (仅支持 2dsphere 索引,指定查询结果的最小距离)
  3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点)

四、实践

  • "$geoIntersects" 操作符找出与查询位置相交的文档 ?

db.driverPoint.find(
   {
     coordinate: {
       $geoIntersects: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 118.19387, 24.592242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)

tips:coordinates 表示多边形,第一个点 和 最后一个点 必须相同,因为这样才能拼成一个对边形呀!

  • "$geoWithin"操作符找出完全包含在某个区域的文档?

db.driverPoint.find(
   {
     coordinate: {
       $geoWithin: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 119.19387, 28.792242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)

  • "$geoWithin"操作符找出矩形范围内的文档?

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
        $box: [
          [ 118.0,24.0 ],
          [ 120.0,30.0 ]
        ]
     }
  }
}
)

tips:"$box"接受一个两元素的数组:第一个元素指定左下角的坐标,第二个元素指定右上角的坐标。

  • "$geoWithin"操作符找出圆形范围内的文档?

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $center: [ [ 118.067678, 24.444373] , 10 ]
     }
  }
}
)

tips:"$center"接受一个两元素数组作为参数:第一个元素是一个点,用于指定圆心;第二个参数用于指定半径。

  • "$geoWithin"操作符找出多边形范围内的文档?

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $polygon: [ [ 118.067678 , 24.444373 ], [ 119.067678 , 25.444373 ], [ 120.067678 , 26.444373 ] ]
     }
  }
}
)

tips:"$polygon" 列表中的最后一个点会被连接到第一个点,以便组成多边形。

  • "$geoWithin"操作符找出球面圆形范围内的文档?

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $centerSphere: [ [ 118.067678, 24.444373 ], 10/3963.2 ]
     }
  }
}
)

tips:该例子表示 距离 [118.067678, 24.444373] 中心点10 英里范围内的所有文档,查询通过除以地球的大约赤道半径(3963.2英里)将距离转换为弧度。

  • $near 找出距离一个点相应距离内的文档?

geoJson 格式(仅支持 2dsphere 索引):

db.driverPoint.find(
{
   coordinate: {
     $near: {
       $geometry: {
          type: "Point" ,
          coordinates: [ 118.067678 , 24.444373 ]
       },
       $maxDistance: 3000,
       $minDistance: 0
     }
   }
}
)

Legacy Coordinate Pairs 格式(仅支持 2d 索引):

db.driverPoint.find(
{
   coordinate: {
     $near: [ 118.193828 , 24.492242 ],
     $maxDistance: 0.10
     }
}
)

tips:1、$near 当用 geoJson 格式表示时打完, 距离单位是米(meter)。

2、$near 当用 Legacy Coordinate Pairs 格式表示时,距离单位是弧度(radian)。

3、"$near"是唯一一个会对查询结果进行自动排序的地理空间操作符:"$near"的返回结果是按照距离由近及远排序的。

五、结语

怎么说呢?学习这方面的知识老是给我一种特别乱的感觉。稍微总结下吧!MongoDB 对于地理空间的查询 是基于 它对 地理空间的索引(即2dsphere 和 2d)来实现的。所以,我们只要搞清楚什么时候 该建立 2dsphere 索引,什么时候该建立 2d 索引,然后再找适用于该索引的操作符就很清晰明了了!总之,geoJSON 格式保存的经纬度一定 建立 2dsphere 索引。Legacy Coordinate Pairs 格式保存的经纬度 仅在表示 平面地图的时候才考虑建立 2d 索引,其他情况还是选择 2dsphere 索引。

参考资料:

1、《MongoDB 权威指南第二版》

2、https://docs.mongodb.com/manual/reference/operator/query-geospatial/

原文地址:https://www.cnblogs.com/jmcui/p/8782887.html

时间: 2024-12-01 17:56:01

MongoDB系列五(地理空间索引与查询).的相关文章

mongoDb地理空间索引和查询

一.MongoDb介绍(http://docs.mongoing.com/manual/applications/geospatial-indexes.html) MongoDB提供了一系列的索引和查询机制来处理地理空间信息.这一节会介绍MongoDB的地理索引特性.您可以阅读 地理索引教程 来了解关于MongoDB中地理查询的完整示例. 表面 在您存储地理数据和编写查询条件前,首先,您必须选择表面类型,这将被用在计算中.您所选择的类型将会影响您的数据如何被存储,建立的索引的类型,以及您的查询的

MongoDB 学习笔记之 地理空间索引入门

地理空间索引: 地理空间索引,可用于处理基于地理位置的查询. Point:用于指定所在的具体位置,我们以restaurants为例: db.restaurants.insert({name: "Citi", loc: {type: "Point", coordinates: [52.37, 5.21]}}) db.restaurants.insert({name: "SAP", loc: {type: "Point", coo

Mongodb地理空间索引

1. LBS地理空间索引 关于LBS相关项目,一般存储每一个地点的经纬度的坐标, 假设要查询附近的场所,则须要建立索引来提升查询效率. Mongodb专门针对这样的查询建立了地理空间索引. 2d和2dsphere索引. 2. 创建索引 建立places集合,来存放地点, loc字段用来存放地区数据GeoJSON Point. db.places.insert( { loc : { type: "Point", coordinates: [ -73.97, 40.77 ] }, name

mongodb学习(五) 查询

1. 按条件查询: db.users.find({"name":"MM1"}) 2.find的第二个参数可以指定要返回的字段:这里1 表示要显示的字段,0 表示要剔除的字段 db.users.find({"name":"MM1"},{"name":1,"age":1}) db.users.find({"name":"MM1"},{"nam

mongodb的地理空间索引常见的问题

创建地理空间索引注意事项 创建地理空间索引失败,提示错误信息如下 > db.places.ensureIndex({"loc":"2dsphere"}){"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"ok" : 0,"errmsg" : "Can't extract geo keys fr

SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础

原文:SQL Server 2008空间数据应用系列二:空间索引(Spatial Index)基础 在前一篇博文中我们学习到了一些关于地理信息的基础知识,也学习了空间参照系统,既地球椭球体.基准.本初子午线.计量单位.投影等相关理论知识,我们可以使用这些空间参照系统组件来定义一系列应用于地球空间上的几何图像来表示地理空间中的特定功能,表示着地球上一个一个特定的位置点. 本篇主要介绍地理空间索引的概念以及微软SQL Server 2008 R2中的空间索引的应用. 一.空间索引 空间索引是指依据空

MongoDB系列教程(八):GridFS存储详解

MongoDB系列教程(八):GridFS存储详解 GridFS简介 mongoDB的文档以BSON格式存储,支持二进制的数据类型,当我们把二进制格式的数据直接保存到mongoDB的文档中.但是当文件太大时,例如图片和视频等文件,每个文档的长度是有限的,于是mongoDb会提供了一种处理大文件的规范--GridFS. GridFS实现原理 在GridFS数据库中,默认使用fs.chunks 和fs.files来存储文件,其中fs.files集合存放文件的信息,fs.chunks存放文件的数据,一

SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型

原文:SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测. 2.具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验. 3.熟悉或了解Microsoft SQL Server 2008中的空间数据类型. 4.具备相应(比如OGC)的GIS专业理论知识. 5.其他相关知识. 通过前面几篇文章介绍了

Apache Kafka系列(五) Kafka Connect及FileConnector示例

Apache Kafka系列(一) 起步 Apache Kafka系列(二) 命令行工具(CLI) Apache Kafka系列(三) Java API使用 Apache Kafka系列(四) 多线程Consumer方案 Apache Kafka系列(五) Kafka Connect及FileConnector示例 一. Kafka Connect简介 Kafka是一个使用越来越广的消息系统,尤其是在大数据开发中(实时数据处理和分析).为何集成其他系统和解耦应用,经常使用Producer来发送消