Location Service v2 で提供される Places の Search Nearby API を利用して、サウナ近くのラーメン屋さんを検索してみる
こんにちは!
クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。
はじめに
みなさんは普段、サウナ行ってますか?サウナといえば、サ飯(サウナの後に食べるご飯)ですよね。
私はサウナに行く時、その後のご飯のことも考えながら、どのサウナを利用しようか考えるタイプの人間です。(つまり食いしん坊ということです。)
最近、AWS Location MCP Server を触る機会がありました。
MCP Server のソースコードを読んでいると、見慣れない API があり、よくよく調べてみると、新しい API が Location Service から提供されていたことがわかりました。
今回はこのうちの Places API を利用して、サウナ後に行くサ飯会場を探してみたいと思います。
Places API
Places API は 108 か国以上の 4 億件以上の住所と興味のある地点 (POI) を含む、包括的な場所データベースにクエリを実行し、場所を検索またはジオコーディング可能な API です。
具体的には、以下の API が提供されています。
- Autocomplete
- ユーザー入力の部分的な情報に基づいて、検索場所や住所を補完 ※日本では利用できない
- Geocode
- テキストで入力された住所や場所を地理座標に変換
- Reverse Geocode
- 地理座標から人が読める住所や場所に変換
- GetPlace
- 特定の場所について、住所、営業時間、連絡先、その他のメタデータなど詳細情報を取得
- Suggest
- ユーザーの入力やコンテキストに基づいて、関連する場所、観光スポット、または検索語句などのインテリジェントな予測や推薦を提供
- Search Text
- テキスト入力から住所、観光スポットを検索し、場所名、住所、電話番号、カテゴリー、料理の種類、連絡先、営業時間などの情報を返す
- Search Nearby
- 指定した地理座標から、一定の半径または距離内で観光スポットや興味のある地点 (POI) を検索
そう、Search Nearby です。
Search Nearby を使えば、サウナの座標から半径 X m 以内のサ飯会場を探せるのではないか?といった企画です。
やってみる
それでは Places API の Search Nearby を使って、サ飯会場を探してみましょう。
今回はラーメン屋さんを想定して探してみます。
サウナ施設の地理座標を取得
今回はあるサウナ施設の住所を元に、座標情報を取得します。
Location Service v2 の geo-places
を利用して、クライアントを生成します。
〒064-0805 北海道札幌市中央区南5条西2丁目1−14 オークラビル
地理座標の取得は Places API の Geocode を利用します。
import json
import boto3
# Location Service v2 を利用する
client = boto3.client('geo-places')
# ジオコーディングを実行する
response = client.geocode(
QueryText='北海道札幌市中央区南5条西2丁目1−14 オークラビル',
Language='ja',
IntendedUse='SingleUse'
)
print(json.dumps(response['ResultItems'], indent=2, ensure_ascii=False))
座標 (Position) が返ってきました。
MatchScores.Overall が 0.99 と非常に高スコアな結果が返ってきています。
{
"PlaceId": "AQAAAGwAieMOJZI4TFLPmI0t-haGKdv0sj1OerkJoB4A4YtJD26S1aY0-C5-N0jeoXvLPWpwYK6X3qD42DyyDlcIkL7FWC3hrzk47c8fZxO0SQdnu6KXa_jJSiLrmtqbJbdVTXkCOhL05h3Fuer-noTcsNJnlARnY544_YAW6hFWMbm6qxZwyhzXA5QE2kCY_PY",
"PlaceType": "PointAddress",
"Title": "〒064-0805 北海道札幌市中央区南5条西2丁目1-14",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西2丁目1-14",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "2丁目",
"SubBlock": "1",
"AddressNumber": "14"
},
"Position": [
141.35561,
43.05436
],
"MapView": [
141.35438,
43.05346,
141.35684,
43.05526
],
"MatchScores": {
"Overall": 0.99,
"Components": {
"Address": {
"Region": 1.0,
"Locality": 1.0,
"District": 1.0,
"SubDistrict": 1.0,
"Block": 1.0,
"SubBlock": 1.0,
"AddressNumber": 1.0,
"Building": 0.83
}
}
}
}
施設近くのラーメン屋さんを検索
お待たせしました。Search Nearby の登場です。
同じく、geo-places
クライアントから API を実行します。
import json
import boto3
# Location Service v2 を利用する
client = boto3.client('geo-places')
# ジオコーディングを実行する
geocode_response = client.geocode(
QueryText='北海道札幌市中央区南5条西2丁目1−14 オークラビル',
Language='ja',
IntendedUse='SingleUse'
)
# 座標から 100 m 以内のラーメン屋さんを検索
search_nearby_response = client.search_nearby(
QueryPosition=geocode_response['ResultItems'][0]['Position'],
QueryRadius=100,
MaxResults=20,
Filter={
'IncludeFoodTypes': [
'japanese-ramen',
]
},
Language='ja',
IntendedUse='SingleUse'
)
print(json.dumps(search_nearby_response['ResultItems'], indent=2, ensure_ascii=False))
次のように 7 件ほどラーメン屋さんがヒットしました!
よくみると、距離 (Distance) 順に結果が返ってきています。
検索結果
[
{
"PlaceId": "AQAAAFUAdMzdh0PCt2Q99J8xa_yFUC4bngd8EGGRxEKNsZQMg9wjq930i7hO_qe4hVXSAwoGjaK7l-rB-4Qv5QT3M44vy8Z4apbKQS9MeNcbNKfW3GBPO8FzYGdVtOYH0LAd2grX7Yi1Eg3NtPJ5vo-w_IBWPQsk2_6E",
"PlaceType": "PointOfInterest",
"Title": "ラーメン輝風",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西3丁目1 ラーメン輝風",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "3丁目",
"SubBlock": "1"
},
"Position": [
141.35476,
43.05436
],
"Distance": 69,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
}
]
},
{
"PlaceId": "AQAAAFUAtLAKUErB1UJARFhRImZ4nPXg-MyMWKk2Bub0GaSxV4jBQ_m4LWqcHKgLSYpsRdSXskGlWL-RfzehqBJmJT-702YcOkToqoze2_VgAwnWhve6XpkLC_m3lv8jA-xUhfZie4OyNMesq2kH-s2GI5Jruo0h9XCE",
"PlaceType": "PointOfInterest",
"Title": "札幌らーめん輝風 すすきの店",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西3丁目1 札幌らーめん輝風 すすきの店",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "3丁目",
"SubBlock": "1"
},
"Position": [
141.35471,
43.0544
],
"Distance": 73,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
},
{
"Id": "restaurant",
"Name": "Restaurant",
"LocalizedName": "レストラン",
"Primary": false
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
}
]
},
{
"PlaceId": "AQAAAFUAqIOjjigpZa60CT3y_EJOpLDMR5OpuGQkBDHWNqXhDuLlkR2nP_AQjl3ebveWpvJzlKBUJ9NZOqB8ISwbBp3E_HlOEBGPM0srBazZrc6Dky3fzftmmIoounVtA_LZRlgYwfZ5-zFmuF7i3R7crtfhrYo1EVSo",
"PlaceType": "PointOfInterest",
"Title": "桜井製麺所 秘密基地すすきの店",
"Address": {
"Label": "〒064-0806 北海道札幌市中央区南6条西3丁目6-26 桜井製麺所 秘密基地すすきの店",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南6条西",
"PostalCode": "064-0806",
"Block": "3丁目",
"SubBlock": "6",
"AddressNumber": "26"
},
"Position": [
141.35486,
43.05383
],
"Distance": 85,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
},
{
"Id": "food_production",
"Name": "Food Production",
"LocalizedName": "食品製造",
"Primary": false
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
},
{
"LocalizedName": "麺類",
"Id": "noodles",
"Primary": false
}
]
},
{
"PlaceId": "AQAAAFUAbcf92jPEv3OGzwBltYnB9QTnC-BExdt3XFws9s4ZW47zehorc3d1qo0ZT2ptWxrMPjLNiPF7s0lVD9cdzjsnrGxi-gcMck8V80L57yuXuHiWgUkzcPJb2hw2nqSg_aJ9kw25CmmZJJoxOpujckB_B-sVtqp7",
"PlaceType": "PointOfInterest",
"Title": "薄野軍鶏そば 嶋や",
"Address": {
"Label": "〒064-0806 北海道札幌市中央区南6条西3丁目6-24 薄野軍鶏そば 嶋や",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南6条西",
"PostalCode": "064-0806",
"Block": "3丁目",
"SubBlock": "6",
"AddressNumber": "24"
},
"Position": [
141.35506,
43.05366
],
"Distance": 90,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
}
]
},
{
"PlaceId": "AQAAAFUAFfTkUe7fl-OgTEv3ZMbTmfEjaT0h-ObKrpaI2v1WbagL6HX5MFZ65b9myDXsO6Gz53-mflncehSRSbic67Dw8MltLQeh02YArCqT0ht6ayuxHssgE0AA8WXxM9ps97VVJNpvGshOjnUwq0qfD_-h3QzdE5YE",
"PlaceType": "PointOfInterest",
"Title": "しみじみ 本店",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西3丁目 しみじみ 本店",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "3丁目"
},
"Position": [
141.35452,
43.05453
],
"Distance": 91,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
},
{
"Id": "restaurant",
"Name": "Restaurant",
"LocalizedName": "レストラン",
"Primary": false
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
},
{
"LocalizedName": "アジア料理",
"Id": "asian",
"Primary": false
}
]
},
{
"PlaceId": "AQAAAFUAV-ZN5Vd1d6NZ2HNoCGSV_Ayw6GcDye7VJ4E3f3nU0CvJIx6rfGFeChI6RdvrmpZqIafdLEMkOvSfV-Qf79RXuLDiL4lh3CIqdy6Euv0s1IAH162NgYuF_w0OeibUjz8gBNexB_pnIxZfEkePUVMo4G8lNPZ4",
"PlaceType": "PointOfInterest",
"Title": "味の華龍",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西3丁目 味の華龍",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "3丁目"
},
"Position": [
141.35451,
43.05455
],
"Distance": 92,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
},
{
"Id": "restaurant",
"Name": "Restaurant",
"LocalizedName": "レストラン",
"Primary": false
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
},
{
"LocalizedName": "アジア料理",
"Id": "asian",
"Primary": false
},
{
"LocalizedName": "日本料理",
"Id": "japanese",
"Primary": false
}
]
},
{
"PlaceId": "AQAAAFUAiNzaxuieBJKo2YzVRxdayZP_K2lHvp1sjoPJiKl0Do_9TSPTKT7Kd_VF3HBoz3Te55gp1OY8_ahmK9Sro4eH70tOuJBzO_NBsq06Qm2hwlW7Nl3kWRApP2OodUiYy2TkDEr4AMBZ6WQCtJQn0qWz2RUpULPU",
"PlaceType": "PointOfInterest",
"Title": "満龍 南5条店",
"Address": {
"Label": "〒064-0805 北海道札幌市中央区南5条西3丁目 満龍 南5条店",
"Country": {
"Code2": "JP",
"Code3": "JPN",
"Name": "日本"
},
"Region": {
"Name": "北海道"
},
"Locality": "札幌市",
"District": "中央区",
"SubDistrict": "南5条西",
"PostalCode": "064-0805",
"Block": "3丁目"
},
"Position": [
141.35449,
43.05451
],
"Distance": 93,
"Categories": [
{
"Id": "casual_dining",
"Name": "Casual Dining",
"LocalizedName": "カジュアルダイニング",
"Primary": true
},
{
"Id": "restaurant",
"Name": "Restaurant",
"LocalizedName": "レストラン",
"Primary": false
}
],
"FoodTypes": [
{
"LocalizedName": "日本食-ラーメン",
"Id": "japanese-ramen",
"Primary": true
},
{
"LocalizedName": "アジア料理",
"Id": "asian",
"Primary": false
}
]
}
]
QueryRadius
QueryRadius では、座標から何メートル以内にある場所を検索するかフィルターするオプションです。
QueryRadius: Defines the search radius around the specified coordinates.
今回、湯冷めしないよう 100 メートル以内を設定しました。
# 座標から 100 m 以内のラーメン屋さんを検索
search_nearby_response = client.search_nearby(
QueryPosition=geocode_response['ResultItems'][0]['Position'],
+ QueryRadius=100,
MaxResults=20,
Filter={
'IncludeFoodTypes': [
'japanese-ramen',
]
},
Language='ja',
IntendedUse='SingleUse'
)
FoodTypes
Filter にはいくつか条件があるのですが、ラーメン屋さん
のような食事処であれば、FoodTypes が利用できます。
ラーメン
の場合、中華料理か日本料理のどちらかを連想することになりますが、日本のラーメン屋さん or 中華料理のどちらかで検索できました。
今回は日本のラーメン屋さん (japanese-ramen) で検索してみました。
# 座標から 100 m 以内のラーメン屋さんを検索
search_nearby_response = client.search_nearby(
QueryPosition=geocode_response['ResultItems'][0]['Position'],
QueryRadius=100,
MaxResults=20,
Filter={
'IncludeFoodTypes': [
+ 'japanese-ramen',
]
},
Language='ja',
IntendedUse='SingleUse'
)
ラーメン屋さん以外にも、以下の FoodTypes で検索をかけられます。(お腹が空いてきました。)
Name | FoodTypes ID |
---|---|
Japanese | japanese |
Japanese-Chanko | japanese-chanko |
Japanese-Curry | japanese-curry |
Japanese-Fish/Other Seafood | japanese-fish/other_seafood |
Japanese-Gyoza | japanese-gyoza |
Japanese-Hibachi | japanese-hibachi |
Japanese-Izakaya | japanese-izakaya |
Japanese-Jingisukan | japanese-jingisukan |
Japanese-Kaiseki | japanese-kaiseki |
Japanese-Okonomiyaki | japanese-okonomiyaki |
Japanese-Ramen | japanese-ramen |
Japanese-Rice Bowl | japanese-rice_bowl |
Japanese-Shabushabu | japanese-shabushabu |
Japanese-Sukiyaki | japanese-sukiyaki |
Japanese-Sushi | japanese-sushi |
Japanese-Sushi Train | japanese-sushi_train |
Japanese-Takoyaki | japanese-takoyaki |
Japanese-Tempura/Other Fried Food | japanese-tempura/other_fried_food |
Japanese-Tonkatsu | japanese-tonkatsu |
Japanese-Udon/Other Noodles | japanese-udon/other_noodles |
Japanese-Unagi/Anago | japanese-unagi/anago |
Japanese-Yakiniku | japanese-yakiniku |
Japanese-Yakitori/Chicken | japanese-yakitori/chicken |
BusinessChains
今回は利用しませんでしたが、有名なチェーン店であれば BusinessChains が利用できます。
具体的な有名具合や、検索可能な名前一覧が見つかりませんが、セブン‐イレブンは調べられるようです。
A businesschain is a chain of businesses that belong to the same brand. For example 7-11.
まとめ
以上、「Location Service v2 で提供される Places の Search Nearby API を利用して、サウナ近くのラーメン屋さんを検索してみる」でした。
検索フィルターが充実していて、難しい作り込みなく簡単に検索できました。便利ですね。
このブログがどなたかの参考になれば幸いです。クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!