对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

地理空间查询

MongoDB 支持对地理空间数据的查询操作。本节介绍了 MongoDB 的地理空间功能。

在 MongoDB 中,您可以将地理空间数据存储为 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 对象或 legacy coordinate pairs 的数据进行查询。您可以使用地理空间索引来提高对地理空间数据的查询性能,或运行某些地理空间查询。

MongoDB 提供两种类型的地理空间索引:

  • 2dsphere 索引,支持解释球体上的几何形状的查询。

  • 2d 索引,支持在平面上解释几何图形的查询。

有关地理空间索引的更多信息,请参阅地理空间索引。

注意

使用 2d 索引查询球形数据可能会返回不正确的结果或错误。例如,2d 索引不支持环绕极点的球形查询。

如果已建立索引的文档在同一 location 子文档中同时包含旧版坐标字段和GeoJSON对象,MongoDB将根据服务器版本选择索引表示形式:

  • 8.2 之前版本的MongoDB根据字段顺序对第一个支持的表示形式进行索引。如果前两个字段是数字, MongoDB会将它们解释为旧版 [longitude, latitude] 对,并忽略后面出现的任何GeoJSON字段。

  • 当子文档包含任何GeoJSON对象时,无论字段顺序如何, MongoDB 8.2 及更高版本始终会对GeoJSON表示形式编制索引。

MongoDB 提供以下地理空间查询操作符:更多详情(包括示例),请参阅各个参考页。

名称
说明

选择与 GeoJSON 几何图形相交的几何图形。2dsphere 索引支持 $geoIntersects。

选择在边界 GeoJSON 几何图形内的几何图形。2dsphere 和 2d 索引支持 $geoWithin。

返回靠近点的地理空间对象。需要地理空间索引。2dsphere 和 2d 索引支持 $near。

返回与球面上的某个点相邻的地理空间对象。需要地理空间索引。2dsphere 和 2d 索引支持 $nearSphere。

注意

时间序列集合仅支持$geoNear 聚合阶段,用于对 2dsphere 索引查询中的地理空间数据进行排序。不能对时间序列集合使用 $near 和 $nearSphere 操作符。

MongoDB 提供以下地理空间聚合管道阶段:

阶段
说明

根据与地理空间点的接近程度返回有序的文档流。针对地理空间数据,整合了 $match、$sort 和 $limit 功能。输出文档包含一个额外的距离字段,并可包含一个位置标识符字段。

$geoNear 需要地理空间索引。

更多详情(包括示例),请参阅 $geoNear 参考页。

MongoDB 地理空间查询可以解释平面或球面上的几何图形。

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

2d 索引支持平面查询(即解释平面上几何图形的查询)和部分球面查询。虽然 2d 索引支持某些球面查询,但对此类球面查询使用 2d 索引可能会导致错误。如果可能,请使用 2dsphere 索引进行球面查询。

下表列出了每个地理空间操作使用的地理空间查询运算符和支持的查询:

操作
球形/平面查询
注意

$near(此行和下一行中的 GeoJSON 质心点,2dsphere 索引)

球形

另请参阅 $nearSphere 操作符,该操作符在与 GeoJSON 和 2dsphere 索引结合使用时可提供相同的功能。

$near(旧版坐标,2 维索引)

平面

$nearSphere(GeoJSON 点,2dsphere 索引)

球形

提供与 $near 操作相同的功能,该操作使用 GeoJSON 点和 2dsphere 索引。

对于球面查询,最好使用在名称中显式指定球面查询的 $nearSphere,而非 $near 运算符。

球形

使用 GeoJSON 点。

球形

$geoWithin : { $box: ... }

平面

$geoWithin : { $polygon: ... }

平面

$geoWithin : { $center: ... }

平面

球形

球形

$geoNear聚合阶段(2 dsphere索引)

球形

$geoNear聚合阶段(2 d索引)

平面

您可以使用 MongoDB Atlas 用户界面在 Atlas 中执行地理空间查询。

1

如果您的地理空间集合还没有地理空间索引,则必须创建一个。

  1. 为该集合选择数据库。

    主面板和左侧的 Namespaces 列出数据库中的集合。

  2. 选择集合。

    在左侧或主面板中选择包含地理空间数据的集合。主面板显示 Find、Indexes 和 Aggregation 视图。

  3. 选择“索引”视图。

    打开 Index 视图后,Atlas 会显示集合中存在的所有索引。

  4. 定义地理类型的索引

    按 Create Index 按钮。

    定义 geo 类型索引。 请参阅如何索引GeoJSON对象。

2
  1. 选择“查找”视图。

    从包含地理空间数据的集合中,选择 Find 标签页以查看地理空间集合。

  2. 输入查询。

    在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 ] ] ] } } }}
  3. 按“应用”按钮。

    按 Apply 按钮应用您的查询。Atlas 会过滤地理空间数据,以仅显示与您的地理空间查询相匹配的文档。

本页上的示例使用来自 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 }]