

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Amazon DocumentDB 查詢地理空間資料
<a name="geospatial"></a>

本節說明如何使用 Amazon DocumentDB 查詢地理空間資料。閱讀本節後，您將能夠回答如何在 Amazon DocumentDB 中儲存、查詢和索引地理空間資料。

**Topics**
+ [概觀](#overview)
+ [索引和儲存地理空間資料](#indexing)
+ [查詢地理空間資料](#querying_geospatial)
+ [限制](#limitations)

## 概觀
<a name="overview"></a>

地理空間的常見使用案例涉及來自資料的鄰近性分析。例如，「尋找距離西雅圖 50 英里內的所有機場」或「從指定位置尋找最近的餐廳」。Amazon DocumentDB 使用 [GeoJSON 規格](https://datatracker.ietf.org/doc/html/rfc7946)來表示地理空間資料。GeoJSON 是座標空間中形狀 JSON 格式的開放原始碼規格。GeoJSON 座標會同時擷取經度和緯度，代表地球狀球體上的位置。

## 索引和儲存地理空間資料
<a name="indexing"></a>

Amazon DocumentDB 使用「Point」GeoJSON 類型來存放地理空間資料。每個 GeoJSON 文件 （或子文件） 通常由兩個欄位組成：
+ **** type - 正在表示的形狀，這會通知 Amazon DocumentDB 如何解譯「座標」欄位。目前，Amazon DocumentDB 僅支援點
+ **coordinates** – 表示為陣列中物件的緯度和經度對 – 【經度、緯度】

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
      ]
   }
});
```

## 查詢地理空間資料
<a name="querying_geospatial"></a>

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
<a name="w2aac47c23c11b9"></a>

在此範例中，您將了解如何尋找與地址 （點） 最接近排序的所有餐廳 （點）。

若要執行這類查詢，您可以使用 `$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` 階段支援 `limit`和 `num`選項來指定要傳回的文件數量上限。如果未指定 `limit`或 `num`選項， 預設會`$geoNear`傳回最多 100 個文件。如果存在且值小於 100，則會由`$limit`階段的值覆寫。

### 範例 2
<a name="w2aac47c23c11c11"></a>

在此範例中，您將了解如何尋找特定地址 （點） 2 公里內的所有餐廳 （點）。若要執行此類查詢，您可以在 `$maxDistance` GeoJSON 點的最小值`$minDistance`和最大值`$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" }
```

## 限制
<a name="limitations"></a>

Amazon DocumentDB 不支援查詢或索引多邊形、LineString、MultiPoint、MultiPolygon、MultiLineString 和 GeometryCollection。