HERE Geocoding & Search v7の/geocodeで日本の住所を指定する際の注意点

HEREにはLocationに関する様々なサービス・機能がある。
例えば、駐車場施設を検索できる**HERE Off-Street Parking API**、渋滞情報を取得できる**HERE Traffic API**、地点間の移動経路を算出してくれる**HERE Routing API**など。
中でも、**Geocoding & Search v7**(以下、**GS7**）という、いわゆる「検索」サービスがあり、どんなものかと思い使ってみたところ、色々とハマってしまったので、備忘録としてここにまとめる。
# GS7で何ができるのか？
「検索」と言っても、様々な「検索」がある様子。
| 検索機能 | 内容 |
|:-----|:-----|
| Discover | フリーワード検索 |
| Autosuggest | ”もしかして”検索 |
| Geocode | 住所から座標を求める検索 |
| Reverse Geocode | 座標から住所を求める検索 |

公式ドキュメントには上記以外の検索方法やそれぞれの使い方、使用例が詳しく書いてある。
忘れやすいので、リンクを貼っておけば後で見れる。
[GS7 Developer Guide](https://www.here.com/docs/bundle/geocoding-and-search-api-developer-guide/page/README.html "HERE公式ドキュメント")

なんとなくどういったことが出来るのか分かったものの、やはり実際に使ってみないとピンとこない。
ということで使ってみたのだが、クセが強くなかなか思い通りにいかなかった。

その失敗談が以下。
# 事前準備
兎にも角にも、HEREのサービスを使うにはアカウント作成やらAPIKEY取得やら、色々とある。
そのあたりは以下記事で分かりやすく書かれているので、一通り従うことにする。

https://qiita.com/kekomat/items/d2e29bac84a27c1ec521

# Geocodeで座標を取得
公式のGeocodeの説明には以下が書かれている。

:::note
The /geocode endpoint is used to find the geo-coordinates of a known address, place, locality or administrative area, even if the query is incomplete or partly incorrect. It also returns a complete postal address string and address details.
:::
テキトーに日本語訳してみると

:::note
/geocodeのendpointを使ってaddressやplace、locality、administrative areaから座標をゲット
:::
「place」「locality」「administrative area」が一体何のことかさっぱりだが、「address」とは恐らく住所のことだろう。
GS7はREST APIなので、Postmanというツールを使って、公式のガイドと同じことをしてみた。

https://www.here.com/docs/bundle/geocoding-and-search-api-developer-guide/page/topics-api/code-geocode-address.html

##### 要求の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/d968af9c-0d80-c578-064a-7cd0c1a4a085.png)

##### レスポンス

```json:response.json
    "items": [
        {
            "title": "240 Washington St, Boston, MA 02108-4603, United States",
            "id": "here:af:streetsection:YCY1nQWrJ5eBrHv075VVOD:CggIBCDns4LfAhABGgMyNDA",
            "resultType": "houseNumber",
            "houseNumberType": "PA",
            "address": {
                "label": "240 Washington St, Boston, MA 02108-4603, United States",
                "countryCode": "USA",
                "countryName": "United States",
                "stateCode": "MA",
                "state": "Massachusetts",
                "county": "Suffolk",
                "city": "Boston",
                "district": "Downtown Boston",
                "street": "Washington St",
                "postalCode": "02108-4603",
                "houseNumber": "240"
            },
            "position": {
                "lat": 42.35814,
                "lng": -71.05765
            },
            "access": [
                {
                    "lat": 42.35815,
                    "lng": -71.05788
                }
            ],
```

確かにガイドと同じような結果になった。
以下部分が座標っぽい。

```json:response.jsonの抜粋
            },
            "position": {
                "lat": 42.35814,
                "lng": -71.05765
            },
```
# 他の指定方法も試してみる

今回要求に使ったパラメータは`APIKEY`と`q`だが、`APIKEY`はサービスを使う上でのパスワードみたいなものだから、実質`q`だけ。もっと他に指定の方法はないのか？
公式のAPIレファレンスというページがあり、使用可能なパラメータの一覧がある。
パラメータの名前と説明文を読んで得たイメージを和訳すると・・・
| パラメータ | 内容 |
|:-----|:-----|
| at | 座標 |
| in | 範囲 |
| limit | レスポンスの最大値 |
| q | フリーテキスト検索ワード |
| qq | Qualified Query。〇〇県とか〇〇市を指定できる |
| lang | レスポンスの言語 |
| types | 「ベータ」らしいから一旦放置 |
| politicalView | 地域の主張。「俺の土地！」の”俺”視点を指定 |
| show | ”もしかして”検索 |

この`qq`というパラメータを使えば、都道府県や市町村を指定し、座標を取得することができそう。
折角なので、HERE事務所の住所を入力して座標をゲットしてみたい。

https://www.here.com/jp/company/about-us

上記公式によると住所は`〒222-0033 神奈川県横浜市港北区新横浜2-5-11 金子第1ビル9階`とのこと。

`qq`というパラメータにはSub-parameterというものが指定できる。指定できるのは以下。
`country`, `state`, `county`, `city`, `district`, `street`, `houseNumber`, `postalCode`.

どうやら上記住所を、`qq`で指定できるSub-parameterに分割してやることで座標が取れるようだ。
ということで、えいやーでやってみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/4349cf89-b141-8dba-f065-9d066dbda09f.png)
一旦、`Country`, `State`, `City`だけでリクエストを出してみた。

##### レスポンス

```json:response.json
    "items": [
        {
            "title": "神奈川県横浜市",
            "id": "here:xs1:namedplace:190475316",
            "resultType": "locality",
            "localityType": "city",
            "address": {
                "label": "神奈川県横浜市",
                "countryCode": "JPN",
                "countryName": "日本",
                "state": "神奈川県",
                "city": "横浜市"
            },
            "position": {
                "lat": 35.4504,
                "lng": 139.63425
            },
```
期待通り。
次は「港北区」。`houseNumber`でも`postalCode`でもなさそうなので、残るは`county`か`district`か`street`のどれか。`district`かな？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/71c1f6c7-8cdb-117e-d488-fee470098057.png)

##### レスポンス

```json:response.json
        {
            "title": "神奈川県横浜市港北区",
            "id": "here:xs1:namedplace:32377123",
            "resultType": "locality",
            "localityType": "district",
            "address": {
                "label": "神奈川県横浜市港北区",
                "countryCode": "JPN",
                "countryName": "日本",
                "state": "神奈川県",
                "city": "横浜市",
                "district": "港北区"
            },
            "position": {
                "lat": 35.51901,
                "lng": 139.63298
            },
```
成功！

:::note
因みに住所の「港北区」、ずっと「みなときたく」と読んでいたが、HEREの住所を調べる時に英語サイトがでてきて「kohoku-ku」とあり、正しくは「こうほくく」であると認識。
日本語って難しい・・・
:::

# 更に絞り込む

次は「新横浜」。使っていないSub-parameterの残りはあと`county`と`street`くらい。
どちらもピンとこないが、とりあえずやってみるしかない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/5049b493-ede8-ef7b-53e6-03167dcede91.png)

##### レスポンス

```json:response.json
    "items": [
        {
            "title": "神奈川県横浜市港北区",
            "id": "here:xs1:namedplace:32377123",
            "resultType": "locality",
            "localityType": "district",
            "address": {
                "label": "神奈川県横浜市港北区",
                "countryCode": "JPN",
                "countryName": "日本",
                "state": "神奈川県",
                "city": "横浜市",
                "district": "港北区"
            },
            "position": {
                "lat": 35.51901,
                "lng": 139.63298
            },
```
`district`までの指定の時と変わらない？　じゃあ`county`ではなく`street`なのか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/60cae6f8-6b18-3797-2dc9-b703f126490a.png)

##### レスポンス

```json:response.json
    "items": [
        {
            "title": "神奈川県横浜市港北区",
            "id": "here:xs1:namedplace:32377123",
            "resultType": "locality",
            "localityType": "district",
            "address": {
                "label": "神奈川県横浜市港北区",
                "countryCode": "JPN",
                "countryName": "日本",
                "state": "神奈川県",
                "city": "横浜市",
                "district": "港北区"
            },
            "position": {
                "lat": 35.51901,
                "lng": 139.63298
            },
```

### あれ？

残ってる`postalCode`や`houseNumber`でやってみたけど、やっぱり結果は同じ。
指定できるSub-parameter全部使ったけど、住所の指定・・・無理ちゃう？

`qq`のパラメータで住所を分割指定できないのであれば、`q`のフリーテキスト検索で住所を全部入れてみるか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/f4c16781-dcf4-995a-634d-10559afd85ec.png)

##### レスポンス

```json:response.json
    "items": [
        {
            "title": "〒222-0033 神奈川県横浜市港北区新横浜2丁目5-11",
            "id": "here:xs1:pointaddress:79413688:CgcIBCDc5-IhEAEaAjExIhLph5HlrZDnrKzkuIDjg5Pjg6s",
            "resultType": "houseNumber",
            "houseNumberType": "PA",
            "address": {
                "label": "〒222-0033 神奈川県横浜市港北区新横浜2丁目5-11",
                "countryCode": "JPN",
                "countryName": "日本",
                "state": "神奈川県",
                "city": "横浜市",
                "district": "港北区",
                "subdistrict": "新横浜",
                "block": "2丁目",
                "subblock": "5",
                "postalCode": "222-0033",
                "houseNumber": "11"
            },
            "position": {
                "lat": 35.50969,
                "lng": 139.61596
            },
```
やっとフル住所が認識された。

### ん？？

```json:response.jsonの抜粋
                "district": "港北区",
                "subdistrict": "新横浜",
                "block": "2丁目",
```
「新横浜」って`subdistrict`なの？
でもSub‐parameterに`subdistrict`ってないけど、
もしかしたら仕様書になくても、実はリクエストしたら通ったりして・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619978/3e64c536-6a56-c376-a972-34b5467937ea.png)

##### レスポンス

```json:response.json
{
    "status": 400,
    "title": "Illegal input for parameter 'qq'",
    "cause": "Actual parameter value: 'country=日本;state=神奈川県;city=横浜市;district=港北区;subdistrict=新横浜'",
    "action": "Unsupported key: 'subdistrict'. Supported keys: 'city', 'country', 'county', 'district', 'houseNumber', 'postalCode', 'state', 'street'",
    "correlationId": "5bf80bf0-1711-47b9-8dc8-2c7c7c0f76d8",
    "requestId": "REQ-729d2cbb-febb-4186-a008-458a7d7f6e08"
}
```
あかんかった。「`subdistrict`は対象外じゃ！」って怒られた。

# 結論

GS7のGeocodeで住所から座標を取得する場合、

- `qq`は日本の住所を完全に分割できないので使わない（使えない）
- 代わりに`q`で求めたい住所をフルに書く

とすれば問題なさそう。

# 補足

北米の住所って大体
【House Number】【Street名】【District名】【市】【州】【Zip Code(郵便番号)】
の形になっている。
欧州も、全く同じでなくても、北米と似て【Street名】があるんだと思う。知らんけど。

日本の住所って、＊＊通りって住所、あるんだろうけど、ポピュラーじゃなさそう。

仕様の設計が欧米基準で作られてるなら、日本の住所体系に完全に対応していなくても頷ける。
とはいえ、`q`を使ってフル住所を入れれば、その座標が返ってくるのはすごい。
この機能を使えば、例えば二つの住所間の距離を測定したい時とか使えそう。