MongoDB 支持对地理空间数据的查询操作。本节介绍了 MongoDB 的地理空间功能。
地理空间数据
在 MongoDB 中,您可以将地理空间数据存储为 GeoJSON 对象或传统坐标对。
GeoJSON 对象
要计算类地球球体的几何形状,请将您的位置数据存储为 GeoJSON 对象。
要指定 GeoJSON 数据,请使用包含以下内容的嵌入式文档:
一个名为
type的字段,用于指定 GeoJSON 对象类型,以及名为
coordinates的字段,指定对象的坐标。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
重要
如果指定纬度和经度坐标,则先列出经度,然后列出纬度。
有效经度值介于
-180和180之间,两者均包括在内。有效纬度值介于
-90和90之间,两者均包括在内。
例如,要指定 GeoJSON 点:
location: { type: "Point", coordinates: [-73.856077, 40.848447] }
有关 MongoDB 支持的 GeoJSON 对象列表和示例,请参阅 GeoJSON 对象。
对 GeoJSON 对象的 MongoDB 地理空间查询在球体上进行计算;MongoDB 使用 WGS84 参考系统对 GeoJSON 对象进行地理空间查询。
传统坐标对
使用传统坐标对对进行带有2d 索引的平面(欧几里得)计算。要执行球面计算,请将旧版对转换为GeoJSON Point 并使用 2dsphere Indexes 索引。
要将数据指定为传统坐标对,可以使用数组(首选)或嵌入式文档。
- 数组:
<field>: [ <x>, <y> ] 使用经度和纬度时,请先列出经度,然后列出纬度:
<field>: [ <longitude>, <latitude> ] 有效经度值介于
-180和180之间,两者均包括在内。有效纬度值介于
-90和90之间,两者均包括在内。
- 嵌入式文档:
<field>: { <field1>: <x>, <field2>: <y> } 如果使用经度和纬度,则第一个字段必须是经度,第二个字段必须是纬度:
<field>: { <field1>: <longitude>, <field2>: <latitude> } 有效经度值介于
-180和180之间,两者均包括在内。有效纬度值介于
-90和90之间,两者均包括在内。
将数组用于传统坐标对,因为某些语言不保留对象字段顺序。
地理空间索引
地理空间索引支持对存储为 GeoJSON 对象或旧版坐标对的数据进行查询。您可以使用地理空间索引来提高对地理空间数据的查询性能,或运行某些地理空间查询。
MongoDB 提供两种类型的地理空间索引:
2dsphere 索引,支持解释球体上的几何形状的查询。
2d 索引,支持在平面上解释几何图形的查询。
有关地理空间索引的更多信息,请参阅地理空间索引。
地理空间查询
注意
使用 2d 索引查询球形数据可能会返回不正确的结果或错误。例如,2d 索引不支持环绕极点的球形查询。
如果已建立索引的文档在同一 location 子文档中同时包含旧版坐标字段和GeoJSON对象,MongoDB将根据服务器版本选择索引表示形式:
8.2 之前版本的MongoDB根据字段顺序对第一个支持的表示形式进行索引。如果前两个字段是数字, MongoDB会将它们解释为旧版
[longitude, latitude]对,并忽略后面出现的任何GeoJSON字段。当子文档包含任何GeoJSON对象时,无论字段顺序如何, MongoDB 8.2 及更高版本始终会对GeoJSON表示形式编制索引。
地理空间查询操作符
MongoDB 提供以下地理空间查询操作符:更多详情(包括示例),请参阅各个参考页。
名称 | 说明 |
|---|---|
选择与 GeoJSON 几何图形相交的几何图形。2dsphere 索引支持 | |
选择在边界 GeoJSON 几何图形内的几何图形。2dsphere 和 2d 索引支持 | |
返回靠近点的地理空间对象。需要地理空间索引。 | |
返回与球面上的某个点相邻的地理空间对象。需要地理空间索引。 |
注意
时间序列集合仅支持$geoNear 聚合阶段,用于对 2dsphere 索引查询中的地理空间数据进行排序。不能对时间序列集合使用 $near 和 $nearSphere 操作符。
地理空间聚合阶段
MongoDB 提供以下地理空间聚合管道阶段:
阶段 | 说明 |
|---|---|
根据与地理空间点的接近程度返回有序的文档流。针对地理空间数据,整合了
|
更多详情(包括示例),请参阅 $geoNear 参考页。
地理空间模型
MongoDB 地理空间查询可以解释平面或球面上的几何图形。
2dsphere 索引仅支持球面查询(即解释球面上几何图形的查询)。
2d 索引支持平面查询(即解释平面上几何图形的查询)和部分球面查询。虽然 2d 索引支持某些球面查询,但对此类球面查询使用 2d 索引可能会导致错误。如果可能,请使用 2dsphere 索引进行球面查询。
下表列出了每个地理空间操作使用的地理空间查询运算符和支持的查询:
操作 | 球形/平面查询 | 注意 |
|---|---|---|
球形 | See also the | |
| 平面 | |
| 球形 | Provides the same functionality as 对于球面查询,最好使用在名称中显式指定球面查询的 |
| 球形 | 使用 GeoJSON 点。 |
| 球形 | |
| 平面 | |
| 平面 | |
| 平面 | |
| 球形 | |
球形 | ||
球形 | ||
平面 |
在 Atlas 中执行地理空间查询
您可以使用 MongoDB Atlas 用户界面在 Atlas 中执行地理空间查询。
查询地理空间数据
选择“查找”视图。
从包含地理空间数据的集合中,选择 Find 标签页以查看地理空间集合。
输入查询。
在Filter文本框中输入查询。使用任意地理空间查询操作符对地理空间数据执行相关查询。地理空间查询可能类似于以下内容:
{ "coordinates": { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [-80.0, 10.00], [ -80.0, 9.00], [ -79.0, 9.0], [ -79.0, 10.00 ], [ -80.0, 10.0 ] ] ] } } } } 按“应用”按钮。
按 Apply 按钮应用您的查询。Atlas 会过滤地理空间数据,以仅显示与您的地理空间查询相匹配的文档。
您可以在 MongoDB Atlas UI 中创建和执行聚合管道,以进行地理空间查询。
创建您的地理空间查询聚合管道
填充聚合阶段。
Fill in your stage with the appropriate values. If Comment Mode is enabled, the pipeline builder provides syntactic guidelines for your selected stage.
修改阶段时,Atlas 会根据当前阶段的结果更新右侧的预览文档。
您的
$geoNear阶段可能类似于:{ near: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, spherical: true, query: { category: "Parks" }, distanceField: "calcDistance" }
示例
本页上的示例使用来自 sample_mflix 数据集的数据。有关如何将此数据集加载到您的自管理 MongoDB 部署中的详细信息,请参阅 加载示例数据集。如果您对示例数据库进行了任何修改,您可能需要删除并重新创建数据库,才能运行此页面上的示例。
sample_mflix.theaters 集合有一个 2dsphere 索引。以下查询使用 $near 操作符返回按从近到远排序的文档。查询返回距离指定 GeoJSON point 至少 1000 米、至多 100000 米的文档:
db.theaters.find( { "location.geo": { $near: { $geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, $minDistance: 1000, $maxDistance: 100000 } } } ).limit(3)
[ { _id: ObjectId('59a47287cfa9a3a73e51eae8'), theaterId: 374, location: { address: { street1: '2478 Central Park Ave', city: 'Yonkers', state: 'NY', zipcode: '10710' }, geo: { type: 'Point', coordinates: [ -73.826805, 40.983246 ] } } }, { _id: ObjectId('59a47287cfa9a3a73e51ead6'), theaterId: 345, location: { address: { street1: '148 Walt Whitman Rd', city: 'Huntington Station', state: 'NY', zipcode: '11746' }, geo: { type: 'Point', coordinates: [ -73.410637, 40.825775 ] } } }, { _id: ObjectId('59a47287cfa9a3a73e51e92f'), theaterId: 200, location: { address: { street1: '3124 Jericho Tpke', city: 'East Northport', state: 'NY', zipcode: '11731' }, geo: { type: 'Point', coordinates: [ -73.319092, 40.838463 ] } } } ]
以下操作使用 $geoNear 聚合操作返回与查询筛选器 { "location.address.state": "NY" } 匹配的文档,这些文档按距离指定 GeoJSON 点从近到远的顺序排序:
db.theaters.aggregate( [ { $geoNear: { near: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, spherical: true, query: { "location.address.state": "NY" }, distanceField: "calcDistance" } }, { $limit: 3 } ] )
[ { _id: ObjectId('59a47287cfa9a3a73e51eae8'), theaterId: 374, location: { address: { street1: '2478 Central Park Ave', city: 'Yonkers', state: 'NY', zipcode: '10710' }, geo: { type: 'Point', coordinates: [ -73.826805, 40.983246 ] } }, calcDistance: 27000 }, { _id: ObjectId('59a47287cfa9a3a73e51ead6'), theaterId: 345, location: { address: { street1: '148 Walt Whitman Rd', city: 'Huntington Station', state: 'NY', zipcode: '11746' }, geo: { type: 'Point', coordinates: [ -73.410637, 40.825775 ] } }, calcDistance: 55000 }, { _id: ObjectId('59a47287cfa9a3a73e51e92f'), theaterId: 200, location: { address: { street1: '3124 Jericho Tpke', city: 'East Northport', state: 'NY', zipcode: '11731' }, geo: { type: 'Point', coordinates: [ -73.319092, 40.838463 ] } }, calcDistance: 72000 } ]