Docs 菜单

按地理空间搜索

在本指南中,您可以学习;了解如何使用Kotlin驾驶员查询地理空间数据。您还可以学习;了解MongoDB支持的不同地理空间数据格式。

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

  • 电影院位置

  • 国家/地区边界

  • 自行车骑行路线

  • 纽约市的狗狗运动区

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

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

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

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

位置表示地球上的单个地点,并以包含两个或三个数值的大量形式给出:

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

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

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

重要

经度然后纬度

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

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

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

要学习;了解有关可在MongoDB中使用的形状的更多信息,请参阅服务器手册中的GeoJSON

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

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

要学习;了解有关 Indexes 构建器的详情,请参阅 索引构建器指南。

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

legacy coordinate pairs 具有以下结构:

{ "location" : [ x, y ] }

该字段值包含一个由两个值组成的大量,其中第一个值表示 x 轴值,第二个值表示 y 轴值。

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

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

要学习;了解有关 Indexes 构建器的详情,请参阅 索引构建器指南。

有关传统坐标对对的更多信息,请参阅服务器手册中地理空间查询指南的传统坐标对部分。

提示

支持的操作符

球面 (2dsphere) 和平面 (2d) 索引支持部分(但不是全部)相同的查询运算符。要查看操作符及其索引兼容性的完整列表,请参阅服务器手册中地理空间查询指南的地理空间查询操作符部分。

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

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

  • $near

  • $geoWithin

  • $nearSphere

  • $geoIntersects 需要 2dsphere 索引

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

要学习;了解有关地理空间查询运算符的更多信息,请参阅服务器手册中地理空间查询指南的地理空间查询运算符部分。

要学习;了解有关 Filters 构建器的详情,请参阅 过滤器构建器 指南。

要指定在地理空间查询中使用的形状,请使用Kotlin驾驶员中的 PositionPointLineStringPolygon 类。

要学习;了解有关GeoJSON形状类的更多信息,请参阅GeoJSON包 API文档。

以下示例使用MongoDB Atlas示例数据集。您可以在Kotlin驱动程序快速入门指南中学习;了解如何设立自己的免费套餐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查询运算符构造查询。

以下示例查询距离中央公园大草坪 100005000 米之间的电影院:

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构建器类的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 参考资料。