Amplify でDeveloper Preview 中のGeoを試す

# TL;DR
先日？3日前？Amplify GeoのDeveloper Previewが開始されたので試す記事です。

**現在 Amplify Geo はDeveloper Preview中であり正式リリースではありません。そのため一部動作が不安定な箇所がある可能性があるため本番環境での利用はお控えいただいた方が良いと思います。**
**また、この記事は2021/08/04 10:00時点の情報で書かれているため、最新版の情報と異なる可能性があります。（Developer Previewのため早いペースで変更が入っている可能性があります）**

公開中のサンプルは以下のリンクからお試しいただけます！

https://als.mierune.io/

ローカル環境ではサンプルでも正常に動作することを確認しましたが、現在Developer Previewのため公開は控えております。


# はじめに
上記サンプルはVue.jsやMaplibreを利用していますが今回はそれらでの利用方法を直接的に説明しているわけではありません。

Vue.jsの利用方法などは他の記事をご覧ください。
なお、公開しているサンプル自体の解説はこの記事ではなく、以下の記事で行っていますのでご覧ください。

https://qiita.com/northprint/items/980371a8dfb6457876d6

また、地図スタイルの日本語化に関しては以下の記事をご覧ください。

https://qiita.com/moritoru/items/c6fc303bf9925de0a3a7

Geo以外のAmplifyの設定等については以下の記事をご覧ください。

https://qiita.com/Nekoya3/items/2cd98071607a6ac74a3b

# 実際にやってみる
## Amplify CLI のプレビューバージョンを入れる
現在AmplifyのGeoはDeveloper PreviewなのでとりあえずAmplify CLIのプレビューバージョンをインストールする必要があります。
`npm install -g @aws-amplify/cli@geo`

## まずMapを試す
### Amplify Appに対してGeoを追加する
`amplify geo add`をする

```shell
Amplify Geo category is in developer preview and not intended for production use at this time.
? Select which capability you want to add: (Use arrow keys)
❯ Map (visualize the geospatial data) 
  Location search (search by places, addresses, coordinates) 
```

今回はMapなのでMapを選択

```shell
? Provide a name for the Map: ALSAmplifySample
```

ALSのMapに対する固有の名前を入れる

```shell
? Who can access this Map? (Use arrow keys)
❯ Authorized users only 
  Authorized and Guest users 
```
誰がMapをみれるか選ぶ。今回はAuthorized user(認証済みユーザー）のみを選択。

```shell
? Are you tracking commercial assets for your business in your app? (Use arrow keys)
❯ No, I only need to track consumers personal mobile devices 
  Yes, I track commercial assets (For example, any mobile object that is tracked by a company in support of its business) 
```

課金形態の選択をする。今回は開発目的のためNoを選択。

```shell
Available advanced settings:
- Map style & Map data provider (default: Streets provided by Esri)

? Do you want to configure advanced settings? Yes
? Specify the map style. Refer https://docs.aws.amazon.com/location-maps/latest/APIReference/API_MapConfiguration.html 
  Streets (data provided by Esri) 
❯ Berlin (data provided by Here) 
  Topographic (data provided by Esri) 
  Navigation (data provided by Esri) 
  LightGrayCanvas (data provided by Esri) 
  DarkGrayCanvas (data provided by Esri) 
```

Map StyleとかMap Data Providerを選びたいのでyesを選び、HEREのBerlinを選択

最終的には以下みたいな選択になります。

```shell
% amplify geo add
Amplify Geo category is in developer preview and not intended for production use at this time.
? Select which capability you want to add: Map (visualize the geospatial data)
? Provide a name for the Map: ALSAmplifySample
? Who can access this Map? Authorized users only
The following choices determine the pricing plan for Geo resources. Learn more at https://aws.amazon.com/location/pricing/
? Are you tracking commercial assets for your business in your app? No, I only need to track consumers personal mobile devices
Successfully set RequestBasedUsage pricing plan for your Geo resources.
Available advanced settings:
- Map style & Map data provider (default: Streets provided by Esri)

? Do you want to configure advanced settings? Yes
? Specify the map style. Refer https://docs.aws.amazon.com/location-maps/latest/APIReference/API_MapConfiguration.html Berlin (data provided by Here)
Successfully added resource ALSAmplifySample locally.

Next steps:
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
```

### とりあえずPushしておく
`amplify push` で環境を上げておきましょう！

```shell
| Category  | Resource name             | Operation | Provider plugin   |
| --------- | ------------------------- | --------- | ----------------- |
| Geo       | ALSAmplifySample          | Create    | awscloudformation |
? Are you sure you want to continue? (Y/n) 

```

カテゴリにGeoが追加されていることを確認してyを入力
CloudFormationのログが流れて終わったらOKです！
もしPushで落ちたら一旦Geoを削除してPullしてから再度追加してPushするとうまくいくかもしれません？？？

Amplify Console(Web)はまだ未対応なようで確認できないためAmazon Location ServiceのMapに行き、追加されていることを確認した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/55f07e93-6e22-e145-37ea-1b57360ec345.png)

### コードをAmplify向けに変える
#### 依存関係の追加
Maplibre向けのAmplifyサポートパッケージの`maplibre-gl-js-amplify`を依存関係に追加します。
(おまけでmaplibre-gl-jsも最新版にあげておく）

```shell
% yarn add maplibre-gl-js maplibre-gl-js-amplify
```

最新版のAmplifyにGeoは含まれていないのでこちらも変更します。

```shell
% yarn add aws-amplify@geo
```

#### コード本体の修正
まずサポートライブラリのインポート(これの依存に`@aws-amplif/geo`がある)

```javascript
import { AmplifyMapLibreRequest } from 'maplibre-gl-js-amplify';
```

あとは、これまでtransformRequestで頑張っていたところを

```javascript
this.map.instance = new maplibregl.Map({
    container: 'map',
    center: [139.7648, 35.6794],
    zoom: 13,
    bearing: 64.8,
    pitch: 60,
    hash: true,
    transformRequest: this.transformRequest,
});
```

AmplifyMapLibreRequestを使うように変えてあげればTransform Requestが不要に

```javascript
this.map.instance = await AmplifyMapLibreRequest.createMapLibreMap({
    container: 'map',
    center: [139.7648, 35.6794],
    zoom: 13,
    bearing: 64.8,
    pitch: 60,
    hash: true,
    region: 'us-west-2',
});
```

pitchやbearingなどが正常に動作していないみたいで初期表示が少し違うが表示できます。
気に入らない場合は直後にpanToしたらいいかなと思います。
https://github.com/aws-amplify/maplibre-gl-js-amplify/pull/25
pitchやbearingなどが正常に動作するようにしたPRを立てたのでいつか対応されるかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/a8494b3d-6e97-dcbf-a4f9-5a7f5f790d3b.png)
 （弊社の独自スタイルを適用しており、わかりやすいように初期表示からすこし動かしています。）
© MIERUNE © OpenStreetMap contributors | © 2021 HERE


これまで必要だったtransformRequestも不要になり、認証の維持のための記述も必要なくなりました。

**めっちゃ簡単になりましたね....**

Amplifyを利用している環境だとMap表示する方法としてこれも一つの方法に入るのではないでしょうか...

## Searchを試す
### Amplify Appに対して改めてGeoを追加する
`amplify geo add`をする

```shell
Amplify Geo category is in developer preview and not intended for production use at this time.
? Select which capability you want to add: (Use arrow keys)
  Map (visualize the geospatial data) 
❯ Location search (search by places, addresses, coordinates) 
```

今回はSearchなのでLocation Searchを選択

```shell
? Provide a name for the Map: ALSAmplifyLocationSearchSample
```

ALSのSearchに対する固有の名前を入れる

```shell
? Who can access this Map? (Use arrow keys)
❯ Authorized users only 
  Authorized and Guest users 
```
誰がSearchできるかを選ぶ。今回はAuthorized user(認証済みユーザー）のみを選択。

```shell
Available advanced settings:
- Search data provider (default: Esri)
- Search result storage location (default: no result storage)

? Do you want to configure advanced settings? Yes
? Specify the data provider of geospatial data for this Search Index: (Use arrow keys)
  Esri 
❯ Here 
? Do you want to cache or store the results of search operations? Refer https://docs.aws.amazon.com/location-places/latest/APIReference/API_DataSourceConfiguration.html (y/N) 
N
```

Map StyleとかMap Data Providerを選びたいのでyesを選び、HEREを選択してデータ保持もしないのでNoを選択

**これだけでLocation Searchが利用可能になります...**

最終的には以下みたいな選択になります。

```shell
 % amplify geo add         
Amplify Geo category is in developer preview and not intended for production use at this time.
? Select which capability you want to add: Location search (search by places, addresses, coordinates)
? Provide a name for the location search index (place index): ALSAmplifyLocationSearch
? Who can access this Search Index? 
❯ Authorized users only 
  Authorized and Guest users 
nekoya3@Nekoya3noMacBook-Pro amazon-location-app % amplify geo add
Amplify Geo category is in developer preview and not intended for production use at this time.
? Select which capability you want to add: Location search (search by places, addresses, coordinates)
? Provide a name for the location search index (place index): ALSAmplifyLocationSearchSample
? Who can access this Search Index? Authorized users only
Available advanced settings:
- Search data provider (default: Esri)
- Search result storage location (default: no result storage)

? Do you want to configure advanced settings? Yes
? Specify the data provider of geospatial data for this Search Index: Here
? Do you want to cache or store the results of search operations? Refer https://docs.aws.amazon.com/location-places/latest/APIReference/API_DataSourceConfiguration.html No
Successfully added resource ALSAmplifyLocationSearchSample locally.

Next steps:
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
```

### とりあえずPushしておく
`amplify push` で環境を上げておきましょう！

```
| --------- | ------------------------------ | --------- | ----------------- |
| Geo       | ALSAmplifyLocationSearchSample | Create    | awscloudformation |
| Geo       | ALSAmplifySample               | No Change | awscloudformation |
? Are you sure you want to continue? Yes

```
カテゴリにGeoが２つになっていることを確認してyを入力
CloudFormationのログが流れて終わったらOKです！

Amplify Console(Web)はまだ未対応なようで確認できないためAmazon Location ServiceのPlace indexesに行き、追加されていることを確認した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/ba939918-80af-a04c-d92c-a1ceaaf03930.png)


### コードをAmplify向けに変える
#### 依存関係の追加
Mapの方ですでにやっていれば不要ですが、geoに対応した`aws-amplify@geo`を入れる

```shell
% yarn add aws-amplify@geo
```

#### コード本体の修正
##### importの修正
これまで

```javascript
import Location from 'aws-sdk/clients/location';
```
とやっていたものを

```javascript
import { Geo } from "aws-amplify";
```
にします。

##### forward Geocodingの修正

```javascript
const Client = new Location({
    credentials: credential,
    region: awsconfig.aws_project_region,
});

const params = {
    IndexName: 'xxxxx',
    MaxResults: 5,
    Text: val,
};
            // 住所検索
Client.searchPlaceIndexForText(params, (err, data) => {
    console.log(data.Results);
});
```
みたいにしていたものを

```javascript
try {
    const data = await Geo.searchByText(val, {
        maxResults: 5,
    });
    console.log(data);
} catch (e) {
    console.error(e);
}
```
にすればOKです。
ただし、これまでの返り値と少し異なっているので注意が必要です。（Resultの中にあるわけではなくdataがそのまま結果です）

##### reverse Geocodingの修正

```javascript
const params = {
    IndexName: 'xxxxxx',
    MaxResults: 1,
    Position: lnglat,
};

this.auth.client.searchPlaceIndexForPosition(params, (err, data) => {
    console.log(data.Result);
});
```
みたいにしていたものを

```javascript
try {
    const data = await Geo.searchByCoordinates(lnglat);
    console.log(data);
} catch (e) {
    console.error(e);
}

```
にすればOKです！
こちらも返り値が一つに限定されるようになっていて扱いやすい印象でした。

# まとめ
AmplifyにAmazon Location Serviceが統合されることで必要な設定の量が減り、扱いやすくなっていました。
また、Amplifyを利用している環境ではAmazon Location Serviceを利用してマップを表示したりジオコーディングすることも多くなるのではないかと思います。

現在はMapとLocation Searchしかないですが、Amplify Geoが正式公開される時にはGeo FencesやRoute Calculators, Trackerも対応していることを祈ります...
(特にTrackerなどはAmplifyとの相性もとても良いと思うので特に対応してくれればいいなと...)

今後もアプリケーションは更新していきます！
（今後も更新のタイミングでQiitaなどでお伝えできるかと思います）

https://als.mierune.io/

# おまけ
今回のサンプルサイトは社内ハッカソンにて制作されたものです
そんな会社風土に憧れるという方、一緒に働いてみませんか？

https://mierune.co.jp/recruit