文档菜单
文档首页
/
MongoDB 手册
/

地理空间查询

本页

  • 兼容性
  • 地理空间数据
  • 地理空间索引
  • 地理空间查询
  • 地理空间模型
  • 在 Atlas 中执行地理空间查询
  • 示例

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

您可以使用地理空间查询在以下环境中部署

  • MongoDB Atlas: 云中 MongoDB 部署的完全托管服务

  • MongoDB Enterprise: 基于订阅的自托管 MongoDB 版本

  • MongoDB Community: 可源代码、免费使用和自托管 MongoDB 版本

对于在 MongoDB Atlas 中托管的部署,您可以通过使用查询筛选栏或聚合构建器在 UI 中运行地理空间查询。有关更多信息,请参阅 在 Atlas 中执行地理空间查询。

在MongoDB中,您可以将地理空间数据存储为GeoJSON对象或作为旧版坐标对。

要计算类似于地球的球体上的几何形状,将您的位置数据存储为GeoJSON对象。

要指定GeoJSON数据,使用具有以下字段的嵌套文档:

  • 名为type的字段,用于指定GeoJSON对象类型,以及

  • 名为 coordinates的字段,用于指定对象的坐标。

<field>: { type: <GeoJSON type> , coordinates: <coordinates> }

重要

如果您指定经纬度坐标,请先列出 经度,然后是 纬度

  • 有效的经度值介于 -180180 之间,两者都包含。

  • 有效的纬度值介于 -9090 之间,两者都包含。

例如,要指定一个GeoJSON点:

location: {
type: "Point",
coordinates: [-73.856077, 40.848447]
}

有关MongoDB支持的GeoJSON对象列表以及示例,请参阅GeoJSON对象。

MongoDB在GeoJSON对象上的地理空间查询是在球体上计算的;MongoDB使用WGS84参考系统在GeoJSON对象上执行地理空间查询。

为了在欧几里得平面上计算距离,将您的位置数据存储为旧坐标对,并使用一个 2d 索引。如果您手动将数据转换为 GeoJSON 点类型,MongoDB 支持使用 2dsphere 索引在旧坐标对上进行球形表面计算。

要将数据指定为旧坐标对,您可以使用数组(推荐)或内嵌文档。

通过数组指定(推荐)
<field>: [ <x>, <y> ]

如果指定经纬度坐标,请先列出 经度,然后是 纬度;即

<field>: [<longitude>, <latitude> ]
  • 有效的经度值介于 -180180 之间,两者都包含。

  • 有效的纬度值介于 -9090 之间,两者都包含。

通过内嵌文档指定
<field>: { <field1>: <x>, <field2>: <y> }

如果指定经纬度坐标,无论字段名称如何,第一个字段必须包含 经度 值,第二个字段包含 纬度 值;即

<field>: { <field1>: <longitude>, <field2>: <latitude> }
  • 有效的经度值介于 -180180 之间,两者都包含。

  • 有效的纬度值介于 -9090 之间,两者都包含。

为了指定旧坐标对,数组比内嵌文档更受欢迎,因为某些语言不能保证关联映射的顺序。

MongoDB 提供以下地理空间索引类型以支持地理空间查询。有关地理空间索引的更多信息,请参阅 地理空间索引

2dsphere 索引支持计算类似于地球的球体上几何形状的查询。

要创建一个 2dsphere 索引,使用 db.collection.createIndex() 方法,并将字符串字面量 "2dsphere" 作为索引类型指定

db.collection.createIndex( { <location field> : "2dsphere" } )

其中 <位置字段> 是一个值可以是 GeoJSON 对象旧版坐标对 的字段。

注意

如果您尝试在包含 GeoJSON 点数组的字段上创建索引,索引构建将失败并返回以下错误

MongoServerError: 索引构建失败

有关 2dsphere 索引的更多信息,请参阅 2dsphere 索引。

2d 索引支持计算在二维平面上几何形状的查询。尽管索引可以支持在球体上计算的 $nearSphere 查询,但如果可能,请使用 2dsphere 索引进行球体查询。

要创建一个 2d 索引,使用 db.collection.createIndex() 方法,将位置字段指定为键,并将字符串字面量 "2d" 作为索引类型

db.collection.createIndex( { <location field> : "2d" } )

其中 <位置字段> 是一个值是 旧版坐标对 的字段。

有关 2d 索引的更多信息,请参阅 2d 索引。

注意

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

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 运算符,当与 GeoJSON2dsphere 索引一起使用时,提供相同的功能。
$near旧坐标2d 索引)
平面
$nearSphereGeoJSON 点,2dsphere 索引)
球形

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

对于球形查询,可能更倾向于使用 $nearSphere,该运算符在名称中明确指定了球形查询,而不是 $near 运算符。

$nearSphere旧坐标2d 索引)
球形
请使用 GeoJSON 点。
球形
$geoWithin : { $box: ... }
平面
$geoWithin : { $polygon: ... }
平面
$geoWithin : { $center: ... }
平面
球形
球形
$geoNear 聚合阶段(2dsphere 索引)
球形
$geoNear 聚合阶段(2d 索引)
平面

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

1

如果您的地理空间集合尚未创建地理空间索引,您必须创建一个。

  1. 选择集合的数据库。

    主面板和左侧的 命名空间 列出数据库中的集合。

  2. 选择集合。

    在左侧面板或主面板中选择包含您的地理空间数据的集合。主面板显示 查找索引聚合 视图。

  3. 选择索引视图。

    当您打开 索引 视图时,Atlas 会显示集合上存在的任何索引。

  4. 定义 geo 类型的索引

    点击 创建索引 按钮。

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

2
  1. 选择查找视图。

    从包含您的地理空间数据的集合中,选择查找选项卡以查看您的地理空间集合。

  2. 输入查询。

    筛选器文本框中输入查询。使用任何地理空间查询运算符对您的地理空间数据执行相关查询。一个地理空间查询可能如下所示

    {
    "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. 按下应用按钮。

    按下应用按钮以应用您的查询。Atlas 将过滤地理空间数据,只显示与您的地理空间查询匹配的文档。

您可以在 MongoDB Atlas UI 中创建和执行聚合管道来执行地理空间查询。

1
  1. 选择集合的数据库。

    主面板和左侧的 命名空间 列出数据库中的集合。

  2. 选择集合。

    在左侧面板或主面板中选择包含您的地理空间数据的集合。主面板显示 查找索引聚合 视图。

  3. 选择聚合视图。

    首次打开聚合视图时,Atlas 会显示一个空聚合管道。

2
  1. 选择聚合阶段。

    在左下角面板中的 选择 下拉列表中选择聚合阶段。

    下拉列表右侧的切换按钮决定了该阶段是否启用。

    使用 $geoNear 阶段在聚合管道中执行地理空间查询。

  2. 填写您的聚合阶段。

    使用适当的值填写您的阶段。如果 注释模式 已启用,管道构建器为您选定的阶段提供语法指南。

    您修改阶段时,Atlas 会根据当前阶段的结果更新右侧的预览文档。

    您的 $geoNear 阶段可能如下所示

    {
    near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
    spherical: true,
    query: { category: "Parks" },
    distanceField: "calcDistance"
    }
  3. 根据需要运行其他管道阶段。

    根据需要添加阶段以完成您的聚合管道。您可能需要添加 $out$merge 以将结果写入视图或当前集合。

创建包含以下文档的集合 places

db.places.insertMany( [
{
name: "Central Park",
location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
category: "Parks"
},
{
name: "Sara D. Roosevelt Park",
location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
category: "Parks"
},
{
name: "Polo Grounds",
location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
category: "Stadiums"
}
] )

以下操作在 location 字段上创建 2dsphere 索引

db.places.createIndex( { location: "2dsphere" } )

上面的 places 集合具有 2dsphere 索引。以下查询使用 $near 操作符返回距离指定的 GeoJSON 点至少 1000 米且最多 5000 米的文档,按从近到远的顺序排序

db.places.find(
{
location:
{ $near:
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)

以下操作使用$geoNear聚合操作来返回匹配查询过滤器{ category: "Parks" }的文档,并按距离指定GeoJSON点的最近到最远排序

db.places.aggregate( [
{
$geoNear: {
near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
spherical: true,
query: { category: "Parks" },
distanceField: "calcDistance"
}
}
] )

返回

文本搜索