type
status
date
slug
summary
tags
category
icon
password
一、经纬度表示方式
MongoDB 中对经纬度的存储有着自己的一套规范(主要是为了可以在该字段上建立地理空间索引)。包括两种方式,分别是 Legacy Coordinate Pairs 和 GeoJSON 。
Legacy Coordinate Pairs
Legacy Coordinate Pairs 又有两种方式可以存储经纬度,可以使用数组(首选)或嵌入式文档。
数组:
- 有效的经度值在 [-180, 180]
- 有效的纬度值在 [-90, 90]
嵌入式文档:
GeoJSON
GeoJson 比 Legacy Coordinate Pairs 要强大的多,Legacy Coordinate Pairs 仅仅用来保存一个经纬度,而 GeoJson 可以用来指定点、线和多边形。一般是下面格式
- <field> 字段的名字可以由用户自定义,但是其中的子对象是由 GeoJSON 指定的,不能改变。
type
:包含下面类型- Point(点)
- LineString(线)
- Polygon(多边形)
- MultiPoint(多点)
- MultiLineString(多个线)
- MultiPolygon(多个多边形)
coordinates
:指定一组坐标,列表形式。
点可以用形如[longitude, latitude]([经度,纬度])的两个元素的数组表示:
线可以用一个由点组成的数组来表示:
多边形的表示方式与线一样(都是一个由点组成的数组),但是
type
不同:二、地理空间索引
2dsphere索引
2dsphere索引用于地球表面类型的地图,允许使用在 Legacy Coordinate Pairs 保存的经纬度字段上和使用 GeoJSON 格式保存的点、线和多边形字段上。
2d索引
对于非球面地图(游戏地图、时间连续的数据等),可以使用 2d 代替 2dsphere。2d 索引仅允许使用在 Legacy Coordinate Pairs 保存的经纬度字段上。
区别
- 球形查询支持:2dsphere 索引只支持球形查询(即球面上几何图形的查询);2d索引支持平面查询(即在平面上几何图形的查询)和一些球形查询。
- 虽然2d索引支持一些球形查询,但是对这些球形查询使用2d索引可能会导致错误,例如极点附近会出现大量的扭曲变形。
- 查询复杂度:2dsphere 索引能够执行复杂查询,包括范围查询、交叉查询等。而 2d 索引只能对点进行索引,所以仅支持基本的几何查询,比如点是否在多边形内等。如果需要执行复杂查询,2dsphere 索引是更好的选择。
- 2d 索引可以保存一个由点组成的数组,但是它只会被保存为由点组成的数组,不会被当成线。特别是对于
$geoWithin
查询来说,这是一项重要的区别。如果将街道保存为由点组成的数组,那么如果其中的某个点位于给定的形状之内,这个文档就会与$geoWithin
相匹配。但是,由这些点组成的线并不一定完全包含在这个形状之内。
- 数据量:2dsphere 索引在处理大规模数据时可能会比较慢,因为它需要计算复杂的球面距离。而 2d 索引在处理大规模数据时性能较好,因为它使用简单的平面几何算法。如果处理的数据量较大,2d 索引是更好的选择。
总结:2dsphere 索引适用于精确的球面距离计算和复杂的地理查询操作,而 2d 索引适用于简单的几何查询和较好的性能。根据具体的需求,我们可以选择合适的索引类型来优化地理空间数据的查询性能。
三、地理空间查询操作符
MongoDB提供以下地理空间查询操作符:
操作符 | ㅤ | 支持的索引 | 几何操作符 | 备注 |
$near | 指出与查询位置附近的从最近到最远的文档。 | 2dsphere、2d | 1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查询结果的最大距离)
2. $minDistance (仅支持 2dsphere 索引,指定查询结果的最小距离。在4.0后支持 2d 索引)
3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点) | 1. $near 当用 geoJson 格式表示时, 距离单位是米(meter)。
2. $near 当用 Legacy Coordinate Pairs 格式表示时,距离单位是弧度(radius)。
3. $near 是唯一一个会对查询结果进行自动排序的地理空间操作符,$near 的返回结果是按照距离由近及远排序的。 |
$geoWithin | 指出完全包含在某个区域的文档。 | 2dsphere、2d | 1. $box(仅支持 2d 索引,查询出矩形范围内的所有文档)
2. $center(仅支持 2d 索引,查询出圆形范围内的所有文档)
3. $polygon (仅支持 2d 索引,查询出多边形范围内的所有文档)
4. $centerSphere(支持 2d 索引和 2dsphere 索引,查询出球面圆形范围内的所有文档)
5. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形) | ㅤ |
$geoIntersects | 指出与查询位置相交的文档。 | 2dsphere | 1. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形) | ㅤ |
$nearSphere | 使用球面几何计算近球面的距离,指出与查询位置从最近到最远的文档。 | 2dsphere、2d | 1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查询结果的最大距离)
2. $minDistance (仅支持 2dsphere 索引,指定查询结果的最小距离。在4.0后支持 2d 索引)
3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点) | ㅤ |
MongoDB 4.0 后对地理空间索引增加的支持
1、地理空间查询操作符 $near 和 $nearSphere 支持查询的分片集合。
2、MongoDB 4.0 为 $geoNear 聚合运算符和 geoNear 命令添加了一个选项 key,使用户可以在查询时指定要使用的地理空间索引。以前,要使用 $geoNear 聚合运算符或 geoNear 命令,集合只能有一个地理空间索引。
四、实践
1、数据准备
2dsphere索引
mongodb 插入测试数据
实体类
创建索引
2d索引
插入测试数据
实体类
创建索引
2、数据查询
1)$near 找出指定位置附近的文档
geoJson 格式(仅支持 2dsphere 索引)
对应的 java 代码
Legacy Coordinate Pairs 格式(仅支持 2d 索引)
对应的 java 代码
2)$geoWithin 找出多边形范围内的文档
$coordinates
表示多边形,第一个点和最后一个点必须相同,这样才能拼成一个多边形geoJson 格式(仅支持 2dsphere 索引)
对应的 java 代码
Legacy Coordinate Pairs 格式(仅支持 2d 索引)
对应的 java 代码
3)找出圆形范围内的文档
Legacy Coordinate Pairs 格式(仅支持 2d 索引)
$center
接受一个两元素数组作为参数:第一个元素是一个点,用于指定圆心;第二个参数用于指定半径。对应的 java 代码
4)$geoWithin 找出矩形范围内的文档
Legacy Coordinate Pairs 格式(仅支持 2d 索引)
$box
接受一个两元素的数组:第一个元素指定左下角的坐标,第二个元素指定右上角的坐标。对应的 java 代码
5)$geoWithin 找出球面圆形范围内的文档
geoJson 格式(仅支持 2dsphere 索引)
对应的 java 代码
6)$geoIntersects 找出与查询位置相交的文档
geoJson 格式(仅支持 2dsphere 索引)
对应的 java 代码
五、结语
geoJSON 格式保存的经纬度一定建立 2dsphere 索引。Legacy Coordinate Pairs 格式保存的经纬度仅在表示平面地图的时候才考虑建立 2d 索引,其他情况还是选择 2dsphere 索引。
- Author:mcbilla
- URL:http://mcbilla.com/article/15ab53bb-9299-47e3-a42a-3a7f4951faaa
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!