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 索引。
JVM系列:JVM命令汇总Log4j2教程
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏