文档菜单
文档首页
/ / /
Kotlin 协程

地理空间搜索

本页内容

  • 概述
  • 地球上的坐标
  • GeoJSON 位置
  • GeoJSON 类型
  • 索引
  • 二维平面上的坐标
  • 索引
  • 地理空间查询
  • 查询运算符
  • 查询参数
  • 示例
  • 按邻近性查询
  • 在范围内查询

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

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

  • 电影院的位置

  • 国家的边界

  • 自行车骑行路线

  • 纽约市的狗运动区域

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

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

"MongoDB Headquarters" : {
"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构建器的更多信息,请参阅我们的关于Indexes构建器的指南.

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

传统坐标对的结构如下

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

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

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

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

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

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

提示

支持的运算符

球形 (2dsphere) 和平面 (2d) 索引支持一些相同的查询运算符,但不支持所有运算符。有关运算符和它们与索引兼容性的完整列表,请参阅 地理空间查询的手动条目。

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

要查询您的地理空间数据,请使用以下查询运算符

  • $near

  • $geoWithin

  • $nearSphere

  • $geoIntersects 需要一个 2dsphere 索引

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

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

有关 Filters 的更多信息,请参阅我们的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
)
}
}

theaters集合已在"${Theater::location.name}.${Theater.Location::geo.name}"字段上创建了2dsphere索引。

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

以下示例查询从中央公园大草坪出发,在10,000米至5,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变量定义的多边形以及代表查询返回的电影院位置的点。

Area of Long Island we are searching for movie theaters

有关$geoWithin运算符的更多信息,请参阅$geoWithin的参考文档。

有关您可以在查询中使用的运算符的更多信息,请参阅MongoDB服务器关于地理空间查询运算符的手册页面。

下一页

MongoDB Kotlin驱动程序