地理空间搜索
概述
在本指南中,您可以学习如何使用 MongoDB Kotlin 驱动程序搜索 地理空间数据,以及 MongoDB 支持的不同地理空间数据格式。
地理空间数据是表示地球表面地理位置的数据。地理空间数据的示例包括
电影院的位置
国家的边界
自行车骑行路线
纽约市的狗运动区域
地球上的坐标
为了在MongoDB中存储和查询您的地理空间数据,请使用GeoJSON。GeoJSON是由互联网工程任务组(IETF)创建的数据格式。
以下是MongoDB总部在GeoJSON中的位置
"MongoDB Headquarters" : { "type": "point", "coordinates": [-73.986805, 40.7620853] }
有关GeoJSON的详细信息,请参阅官方IETF规范.
GeoJSON位置
位置表示地球上单个位置,在代码中以包含两个或三个数值的数组形式存在
第一位置为经度(必需)
第二位置为纬度(必需)
第三位置为海拔(可选)
重要
经度后跟纬度
GeoJSON按照经度优先、纬度第二的顺序排列坐标。这与地理坐标系统惯例通常列出的纬度第一、经度第二的顺序可能不同。请确保检查您正在使用的任何其他工具使用的格式。流行的工具,如OpenStreetMap和Google Maps,按照纬度第一、经度第二的顺序列出坐标。
GeoJSON类型
您的GeoJSON对象类型决定了它的几何形状。几何形状由位置组成。
以下是常见的GeoJSON类型以及如何使用位置指定它们
点
:单个位置。这可能代表一个雕塑。线字符串
:两个或更多位置的数组,因此形成了一系列线段。这可能代表中国长城的路线。多边形
:一个位置数组,其中第一个和最后一个位置相同,因此包围一定空间。这可以表示 梵蒂冈城内的土地。
要了解您可以在MongoDB中使用哪些形状,请参阅 GeoJSON手册条目。
索引
要查询存储在GeoJSON格式中的数据,将包含GeoJSON数据的字段添加到2dsphere
索引中。以下代码示例使用Indexes
构建器在location.geo
字段上创建一个2dsphere
索引。
collection.createIndex((Indexes.geo2dsphere("location.geo")))
有关Indexes
构建器的更多信息,请参阅我们的关于Indexes构建器的指南.
二维平面上的坐标
您可以使用二维欧几里得平面上的x
和y
坐标来存储地理空间数据。我们称二维平面上的坐标为“传统坐标对”。
传统坐标对的结构如下
"<field name>" : [ x, y ]
您的字段应包含一个包含两个值的数组,其中第一个值代表 x
轴值,第二个值代表 y
轴值。
索引
要查询存储为旧坐标对的旧数据,您必须将包含旧坐标对的字段添加到 2d
索引中。以下代码片段使用 Indexes
构建器在 coordinates
字段上创建一个 2d
索引。
collection.createIndex((Indexes.geo2d("coordinates")))
有关 Indexes
构建器的更多信息,请参阅我们的 Indexes 构建器指南。
有关旧坐标对的更多信息,请参阅 MongoDB 服务器手册中的旧坐标对页面。
地理空间查询
地理空间查询由查询运算符和 GeoJSON 形状作为查询参数组成。
查询运算符
要查询您的地理空间数据,请使用以下查询运算符
$near
$geoWithin
$nearSphere
$geoIntersects
需要一个 2dsphere 索引
您可以使用 MongoDB Kotlin 驱动程序中的 near()
、geoWithin()
、nearSphere()
和 geoIntersects()
实用方法在 Filters
构建类中指定这些查询运算符。
有关地理空间查询运算符的更多信息,请参阅地理空间查询的手册条目。
有关 Filters
的更多信息,请参阅我们的Filters 构建器指南。
查询参数
要指定用于地理空间查询的形状,请使用 MongoDB Kotlin 驱动程序中的 Position
、Point
、LineString
和 Polygon
类。
关于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
变量定义的多边形以及代表查询返回的电影院位置的点。

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