Docs 菜单
Docs 主页
/ / /
Kotlin 协程
/ / /

按地理空间搜索

在此页面上

  • 概述
  • 地球坐标
  • GeoJSON 位置
  • GeoJSON 类型
  • 指数
  • 2D 平面上的坐标
  • 指数
  • 地理空间查询
  • 查询运算符
  • 查询参数
  • 举例
  • 按距离查询
  • 在范围内查询

在本指南中,您可以了解如何使用 MongoDB Kotlin 驱动程序搜索地理空间数据,以及 MongoDB 支持的不同地理空间数据格式。

地理空间数据是表示地球表面地理位置的数据。 地理空间数据的示例包括:

  • 电影院位置

  • 国家/地区边界

  • 自行车骑行路线

  • 纽约市的狗狗运动区

要在 MongoDB 中存储和查询地理空间数据,请使用GeoJSON 。 GeoJSON 是由互联网工程任务组 (IETF) 创建的一种数据格式。

以下是 GeoJSON 中 MongoDB 总部的位置:

"MongoDB Headquarters" : {
"type": "point",
"coordinates": [-73.986805, 40.7620853]
}

有关 GeoJSON 的明确信息,请参阅 官方 IETF 规范。

位置表示地球上的单个位置,在代码中作为包含两个或三个数值的数组存在:

  • 第一个位置的经度(必需)

  • 第二个位置的纬度(必需)

  • 第三个位置的海拔高度(选填)

重要

经度然后纬度

GeoJSON 将坐标排序为经度在前,纬度在后。 这可能令人惊讶,因为地理坐标系惯例通常首先列出纬度,然后列出经度。 请务必检查您正在使用的其他工具所使用的格式。 OpenStreetMap 和 Google Maps 等流行工具以纬度在前、经度在后的方式列出坐标。

GeoJSON 对象的类型决定了其几何形状。 几何形状由多个位置组成。

下面是一些常见的 GeoJSON 类型以及如何使用位置指定这些类型:

  • Point:单个位置。 这可以代表 雕塑的位置。

  • LineString:由两个或多个位置组成的数组,从而形成一系列线段。 这可能代表 中国长城的路线。

  • Polygon:位置数组,其中第一个和最后一个位置相同,因此包含一些空格。 这可能代表 梵蒂冈城内的土地。

要进一步了解可在 MongoDB 中使用的形状,请参阅GeoJSON 手册条目。

要查询以 GeoJSON 格式存储的数据,请将包含 GeoJSON 数据的字段添加到2dsphere索引中。 以下代码片段使用Indexes构建器在location.geo字段上创建2dsphere索引:

collection.createIndex((Indexes.geo2dsphere("location.geo")))

有关Indexes构建器的更多信息,请参阅我们有关索引构建器指南。

您可以使用二维欧几里得平面上的xy坐标来存储地理空间数据。 我们将二维平面上的坐标称为“legacy coordinate pairs”。

legacy coordinate pairs 具有以下结构:

"<field name>" : [ x, y ]

您的字段应包含一个由两个值组成的数组,其中第一个值代表 x 轴值,第二个值代表 y 轴值。

要查询存储为传统坐标对的数据,必须将包含传统坐标对的字段添加到2d索引中。 以下代码片段使用Indexes构建器在coordinates字段上创建2d索引:

collection.createIndex((Indexes.geo2d("coordinates")))

有关Indexes构建器的更多信息,请参阅我们的索引构建器指南。

有关旧版坐标对的更多信息,请参阅 MongoDB 服务器手册中有关旧版坐标对的页面

提示

支持的操作符

球面 (2dsphere) 和平面 (2d) 索引支持一部分(而非全部)相同查询操作符。有关操作符及其索引兼容性的完整列表,请参阅地理空间查询手册条目

地理空间查询由查询操作符和作为查询参数的 GeoJSON 形状组成。

要查询地理空间数据,请使用以下查询运算符之一:

  • $near

  • $geoWithin

  • $nearSphere

  • $geoIntersects 需要 2dsphere 索引

您可以使用Filters构建器类的near()geoWithin()nearSphere()geoIntersects()实用程序方法在 MongoDB Kotlin 驱动程序中指定这些查询操作符。

有关地理空间查询操作符的更多信息,请参阅地理空间查询的手册条目。

有关Filters的更多信息,请参阅我们的筛选器构建器指南。

要指定在地理空间查询中使用的形状,请使用 MongoDB Kotlin 驱动程序的PositionPointLineStringPolygon类。

有关 MongoDB Kotlin 驱动程序中可用的 GeoJSON 形状的完整列表,请参阅 GeoJSON 包 API 文档。

以下示例使用 MongoDB Atlas 样本数据集。您可以学习如何设置自己的免费套餐 Atlas 集群,并在我们的快速入门指南中了解如何加载样本数据集。

示例使用了示例数据集 sample_mflix 数据库中的 theaters 集合。

这些示例需要进行以下导入:

import com.mongodb.client.model.geojson.Point
import com.mongodb.client.model.geojson.Polygon
import com.mongodb.client.model.geojson.Position
import com.mongodb.client.model.Filters.near
import com.mongodb.client.model.Filters.geoWithin
import com.mongodb.client.model.Projections.fields
import com.mongodb.client.model.Projections.include
import com.mongodb.client.model.Projections.excludeId

使用以下 Kotlin 数据类对数据进行建模:

data class Theater(
val theaterId: Int,
val location: Location
) {
data class Location(
val address: Address,
val geo: Point
) {
data class Address(
val street1: String,
val street2: String? = null,
val city: String,
val state: String,
val zipcode: String
)
}
}

结果使用以下 Kotlin 数据类进行建模:

data class TheaterResults(
val location: Location
) {
data class Location(
val address: Address
) {
data class Address(
val city: String
)
}
}

theaterscollection已包含"${Theater::location.name}.${Theater.Location::geo.name}"字段上的2dsphere索引。

要按从最近到最远的顺序搜索并返回文档,请使用Filters构建器类的near()静态实用程序方法。 near()方法使用$near查询运算符构造查询。

以下示例查询距离中央公园大草坪10,0005,000米之间的剧院:

val database = client.getDatabase("sample_mflix")
val collection = database.getCollection<TheaterResults>("theaters")
val centralPark = Point(Position(-73.9667, 40.78))
val query = Filters.near(
"${Theater::location.name}.${Theater.Location::geo.name}", centralPark, 10000.0, 5000.0
)
val projection = Projections.fields(
Projections.include(
"${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"),
Projections.excludeId()
)
val resultsFlow = collection.find(query).projection(projection)
resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Bronx)))
TheaterResults(location=Location(address=Address(city=New York)))
TheaterResults(location=Location(address=Address(city=New York)))
TheaterResults(location=Location(address=Address(city=Long Island City)))
TheaterResults(location=Location(address=Address(city=New York)))
TheaterResults(location=Location(address=Address(city=Secaucus)))
TheaterResults(location=Location(address=Address(city=Jersey City)))
TheaterResults(location=Location(address=Address(city=Elmhurst)))
TheaterResults(location=Location(address=Address(city=Flushing)))
TheaterResults(location=Location(address=Address(city=Flushing)))
TheaterResults(location=Location(address=Address(city=Flushing)))
TheaterResults(location=Location(address=Address(city=Elmhurst)))

提示

有趣的事实

MongoDB 使用与 GPS 卫星相同的参考系来计算地球上空的几何形状。

有关$near操作符的更多信息,请参阅$near 的参考文档。

有关Filters的更多信息,请参阅我们的筛选器构建器指南。

要搜索指定形状内的地理空间数据,请使用Filters构建器类的geoWithin()静态实用程序方法。 geoWithin()方法使用$geoWithin查询运算符构造查询。

以下示例搜索长岛某个地区的电影院。

val longIslandTriangle = Polygon(
listOf(
Position(-72.0, 40.0),
Position(-74.0, 41.0),
Position(-72.0, 39.0),
Position(-72.0, 40.0)
)
)
val projection = Projections.fields(
Projections.include(
"${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"),
Projections.excludeId()
)
val geoWithinComparison = Filters.geoWithin(
"${Theater::location.name}.${Theater.Location::geo.name}", longIslandTriangle
)
val resultsFlow = collection.find<TheaterResults>(geoWithinComparison)
.projection(projection)
resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Baldwin))))
TheaterResults(location=Location(address=Address(city=Levittown)))
TheaterResults(location=Location(address=Address(city=Westbury)))
TheaterResults(location=Location(address=Address(city=Mount Vernon)))
TheaterResults(location=Location(address=Address(city=Massapequa)))

下图显示了由longIslandTriangle变量定义的多边形以及表示查询返回的电影院位置的点。

我们正在搜索电影院的长岛地区

有关$geoWithin操作符的更多信息,请参阅$geoWithin 的参考文档

有关可在查询中使用的操作符的更多信息,请参阅MongoDB Server 手册中有关地理空间查询操作符的页面

后退

指定要返回的字段

来年

搜索文本