通过 Amazon DocumentDB 查询地理空间数据
本节将介绍可以怎样使用 Amazon DocumentDB 来查询地理空间数据。阅读本节后,您将能够回答如何在 Amazon DocumentDB 中存储、查询和索引化地理空间数据。
概述
地理空间的常见用例涉及来自数据的邻近分析。例如,“查找距离西雅图 50 英里范围内的所有机场”,或“查找距离给定位置最近的餐厅”。Amazon DocumentDB 使用 GeoJSON 规范
索引化和存储地理空间数据
Amazon DocumentDB 使用“点” GeoJSON 类型来存储地理空间数据。每个 GeoJSON 文档(或子文档)通常由两个字段组成:
-
类型 — 要被表示的形状,它告知 Amazon DocumentDB 如何解释“坐标”字段。目前,Amazon DocumentDB 仅支持点
-
坐标 — 表示为数组中对象的经纬度对 — [经度、纬度]
Amazon DocumentDB 还使用 2dsphere 索引来索引化地理空间数据。Amazon DocumentDB 支持索引化点。Amazon DocumentDB 支持用 2dsphere 索引化进行邻近查询。
让我们考虑一个场景,即您正在为送餐服务构建一个应用程序。您希望要在 Amazon DocumentDB 中存储各种餐厅的经纬度对。为此,我们首先建议您对地理空间字段创建一个包含经纬度对的索引。
use restaurantsdb db.usarestaurants.createIndex({location:"2dsphere"})
该命令的输出内容类似如下所示:
{ "createdCollectionAutomatically" : true, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
创建索引后,您可以开始将数据插入 Amazon DocumentDB 集合。
db.usarestaurants.insert({ "state":"Washington", "city":"Seattle", "name":"Thai Palace", "rating": 4.8, "location":{ "type":"Point", "coordinates":[ -122.3264, 47.6009 ] } }); db.usarestaurants.insert({ "state":"Washington", "city":"Seattle", "name":"Noodle House", "rating": 4.8, "location":{ "type":"Point", "coordinates":[ -122.3517, 47.6159 ] } }); db.usarestaurants.insert({ "state":"Washington", "city":"Seattle", "name":"Curry House", "rating": 4.8, "location":{ "type":"Point", "coordinates":[ -121.4517, 47.6229 ] } });
查询地理空间数据
Amazon DocumentDB 支持对地理空间数据的邻近查询、包含查询和交叉点查询。一个良好的邻近查询示例是查找距另一个点(城市)小于某个距离且大于某个距离的所有点(所有机场)。一个良好的包含项查询示例是查找位于指定区域/多边形(纽约州)的所有点(所有机场)。一个良好的交叉点查询示例是查找与某个点(城市)相交的多边形(州)。您可以使用以下地理空间运算符从数据中获取见解。
-
$nearSphere
-$nearSphere
是一个查找运算符,支持查找距 GeoJSON 点最近处到最远处的点。 -
$geoNear
-$geoNear
是一个聚合运算符,支持计算以米为单位的距 GeoJSON 点的距离。 -
$minDistance
-$minDistance
是一个查找运算符,结合$nearSphere
或$geoNear
一起用于筛选距中心点至少指定最小距离的文档。 -
$maxDistance
-$maxDistance
是一个查找运算符,结合$nearSphere
或$geoNear
一起用于筛选距中心点至多指定最大距离的文档。 -
$geoWithin
-$geoWithin
是一个查找运算符,支持查找包含具有以下地理空间数据的文档,这些数据完全存在于指定形状(如多边形)范围内。 -
$geoIntersects
-$geoIntersects
是一个查找运算符,支持查找其地理空间数据与指定 GeoJSON 对象相交的文档。
注意
$geoNear
和 $nearSphere
要求您在邻近查询中使用的 GeoJSON 字段上有 2dsphere 索引。
示例 1
在此示例中,您将学习如何查找按照距某地址(点)最近距离排序的所有餐厅(点)。
要执行这样的查询,您可以使用 $geoNear
计算一组点距另一点的距离。您也可以添加 distanceMultiplier
来测量以千米计的距离。
db.usarestaurants.aggregate([ { "$geoNear":{ "near":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "spherical":true, "distanceField":"DistanceKilometers", "distanceMultiplier":0.001 } } ])
上述命令将返回按照距指定点的距离(最近到最远)排序的餐厅。该命令的输出内容类似如下所示
{ "_id" : ObjectId("611f3da985009a81ad38e74b"), "state" : "Washington", "city" : "Seattle", "name" : "Noodle House", "rating" : 4.8, "location" : { "type" : "Point", "coordinates" : [ -122.3517, 47.6159 ] }, "DistanceKilometers" : 0.03422834547294996 } { "_id" : ObjectId("611f3da185009a81ad38e74a"), "state" : "Washington", "city" : "Seattle", "name" : "Thai Palace", "rating" : 4.8, "location" : { "type" : "Point", "coordinates" : [ -122.3264, 47.6009 ] }, "DistanceKilometers" : 2.5009390081704277 } { "_id" : ObjectId("611f3dae85009a81ad38e74c"), "state" : "Washington", "city" : "Seattle", "name" : "Curry House", "rating" : 4.8, "location" : { "type" : "Point", "coordinates" : [ -121.4517, 47.6229 ] }, "DistanceKilometers" : 67.52845344856914 }
要限制查询中的结果数量,可使用 limit
或 num
选项。
limit
:
db.usarestaurants.aggregate([ { "$geoNear":{ "near":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "spherical":true, "distanceField":"DistanceKilometers", "distanceMultiplier":0.001, "limit": 10 } } ])
num
:
db.usarestaurants.aggregate([ { "$geoNear":{ "near":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "spherical":true, "distanceField":"DistanceKilometers", "distanceMultiplier":0.001, "num": 10 } } ])
注意
$geoNear
stage 支持 limit
和 num
选项来指定要返回的最大文档数。如果未指定 limit
或 num
选项,则 $geoNear
默认最多返回 100 个文档。如果存在 $limit
stage 的值且此值小于 100,则文档数会被此值覆盖。
示例 2
在此示例中,您将学习如何查找距特定地址(点)2 千米范围内的所有餐厅(点)。要执行此类查询,您可以在距 GeoJSON 点的最小值 $minDistance
和最大值 $maxDistance
范围内使用 $nearSphere
db.usarestaurants.find({ "location":{ "$nearSphere":{ "$geometry":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "$minDistance":1, "$maxDistance":2000 } } }, { "name":1 })
上面的命令将返回距指定点最大距离 2 千米的餐厅。该命令的输出内容类似如下所示
{ "_id" : ObjectId("611f3da985009a81ad38e74b"), "name" : "Noodle House" }
限制
Amazon DocumentDB 不支持对多边形、LineString、MultiPoint、MultiPolygon、MultilityString 和 GeometryCollection 查询或索引化。