Geocoding API v4 では、API の v3 の機能を置き換えるいくつかの新しいメソッドが導入されています。このガイドでは、新しい v4 メソッドを使用するようにアプリを移行する方法について説明します。
既存の API キーを新しい v4 メソッドで使用できます。ただし、API の v3 で割り当ての引き上げをリクエストした場合は、新しい v4 API で引き上げをリクエストする必要があります。
v3 のフォワード ジオコーディングから移行する
v3 Geocoding を使用して住所をジオコーディングしている場合は、GET リクエストを受け入れる v4 の 住所をジオコーディングするメソッドに移行する必要があります。
v4 API では、いくつかのパラメータの名前、構造、サポートが変更されています。フィールド マスクを使用して、レスポンスで返すフィールドを指定することを強くおすすめします。
リクエスト パラメータの変更
| v3 パラメータ | v4 パラメータ | メモ |
|---|---|---|
address、components |
address |
非構造化アドレス(v3 address)が URL パスで渡されるようになりました。構造化された住所コンポーネント(v3 components)は、address.* クエリ パラメータとして渡すことができます。v3 コンポーネント フィルタを再現するをご覧ください。 |
bounds |
locationBias.rectangle |
名前を変更。構造をオブジェクトに変更。 |
language |
languageCode |
名前を変更しました。省略した場合、v3 では Accept-Language ヘッダーが使用されるか、デフォルトで en が使用されます。一方、v4 では、デフォルトでその場所の現地の言語と文字が使用されます。 |
region |
regionCode |
名前を変更しました。省略すると、v3 のデフォルトは us になりますが、v4 にはデフォルト値がありません。 |
extra_computations |
削除済み | SearchDestinations メソッドに置き換えられました。 |
レスポンス フィールドの変更
| v3 フィールド | v4 フィールド | メモ |
|---|---|---|
status、error_message |
削除済み | v4 では HTTP ステータス コードとエラー本文を使用します。 |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
名前を変更しました。 |
results.geometry.location_type |
results.granularity |
名前を変更しました。 |
results.geometry.location |
results.location |
フィールド名: lat/lng -> latitude/longitude。 |
results.geometry.viewport |
results.viewport |
フィールド名: northeast/southwest -> high/low。 |
results.postcode_localities |
results.postalCodeLocalities |
名前を変更しました。1 つ以上の地域に対して返されるようになりました(v3 では 1 つ以上が必要)。 |
results.partial_match |
削除済み | |
| 新機能 | results.addressComponents.languageCode |
特定のアドレス コンポーネントの言語。 |
| 新機能 | results.bounds |
high / low を使用した明示的な境界。 |
| 新機能 | results.place |
場所のリソース名。 |
| 新機能 | results.postalAddress |
構造化された PostalAddress オブジェクト。 |
v3 コンポーネント フィルタを再現する
Geocoding v3 のフォワード ジオコーディングには、特定のコンポーネント(components=country:US など)の結果をハード フィルタリングできる components パラメータが含まれていました。v4 のフォワード ジオコーディングでは、リクエスト パラメータでのこのタイプのハード フィルタリングはサポートされていません。v4 では、住所情報をパス内の単一の非構造化文字列として指定することも、address.addressLines、address.locality、address.administrativeArea、address.postalCode、address.regionCode などの構造化クエリ パラメータとして指定することもできます。構造化パラメータは、ハードフィルタとして機能しません。代わりに、指定されたすべてのコンポーネントが結合され、API がジオコーディングを試みる完全な住所が形成されます。API は、すべてのコンポーネントで指定された住所全体に最も一致するものを検索します。コンポーネントを構造化された方法で提供すると、特に住所情報が個別のフォーム フィールドから収集される場合に、API が意図をより適切に理解できるようになります。各フィールドの情報タイプが明確であるため、API が各コンポーネント内の軽微な入力ミスや曖昧さを処理するのに役立ちます。
v3 のハード コンポーネント フィルタと同様の動作を実現するには、レスポンスの postalAddress オブジェクトと addressComponents オブジェクトに基づいて、v4 API から返された results 配列にクライアントサイド フィルタを実装する必要があります。
次の表に、v3 components フィルタと v4 postalAddress フィールドの最適な一致を示します。
| v3 コンポーネント フィルタ | v4 レスポンス フィールド |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea または addressComponents |
クライアントサイドのフィルタリングの例
次の例は、サポートされているフィールド(国、行政区域、郵便番号)で v3 コンポーネント フィルタリングと同様の動作を実現するために、結果をフィルタリングする方法を示しています。信頼できるフィルタリング条件が存在しないため、他のフィールドでフィルタリングすることはおすすめしません。
国でフィルタ
リクエストの address.regionCode と各結果の postalAddress.regionCode を照合します。API はリクエストで小文字の地域コードを受け入れますが、レスポンスでは常に大文字で返します。そのため、比較する前に、入力を大文字に正規化する必要があります。
Python コードの例
def filter_by_country(results, region_code): return [ res for res in results if res.get('postalAddress', {}).get('regionCode') == region_code.upper() ] # Example usage: # v4_response = ... # API call response # filtered = filter_by_country(v4_response.get('results', []), 'US')
Node.js のコード例
function filterByCountry(results, regionCode) { return results.filter(res => res.postalAddress?.regionCode === regionCode.toUpperCase()); } // Example usage: // const v4Response = ... # API call response // const filtered = filterByCountry(v4Response.results, 'US');
行政区域でフィルタ
リクエストの address.administrativeArea と各結果の postalAddress.administrativeArea を照合します。国コードと同様に、比較する前に、入力を大文字に正規化する必要があります。これは、リクエストの administrativeArea に標準の 2 文字の略称が指定されている場合にのみ信頼できます。レスポンスの postalAddress.administrativeArea が ISO 3166-2 コードのサフィックスと直接一致しない理由はいくつかあります。まず、一部の地域では、ISO 3166-2 コードに対応する区分が、郵便番号の標準的な表記に含まれていません。たとえば、スペインでは、行政区域レベル 1(例: カナリア諸島の「CN」)が addressComponents に含まれる場合がありますが、postalAddress.administrativeArea にはレベル 2 の区域(例: 「サンタ クルス デ テネリフェ」)が含まれる場合があります。次に、一部の地域では、行政区画の略称が一般的に使用されておらず、postalAddress.administrativeArea では長い名前で表されます(同様の理由で、行政区画に対応する住所コンポーネントの addressComponents.shortText が、行政区画の ISO 3166-2 コードのサフィックスと一致しない場合があります)。また、場合によっては、administrative_area_level_n の住所コンポーネントで、n が 1 より大きい値で表されることもあります。
最も包括的な結果を得るには、postalAddress.administrativeArea と administrative_area_level_n タイプ(administrative_area_level_1 など)の addressComponents の両方で一致を確認する必要があります。
Python コードの例
def filter_by_admin_area(results, admin_area): target = admin_area.upper() filtered = [] for res in results: # Check postalAddress pa_aa = res.get('postalAddress', {}).get('administrativeArea', '') if pa_aa == target: filtered.append(res) continue # Check all administrative area levels in addressComponents for comp in res.get('addressComponents', []): is_admin_level = any(t.startswith('administrative_area_level_') for t in comp.get('types', [])) if is_admin_level: short = comp.get('shortText', '') if short == target: filtered.append(res) break return filtered # Example usage: # filtered = filter_by_admin_area(v4_response.get('results', []), 'CA')
Node.js のコード例
function filterByAdminArea(results, adminArea) { const target = adminArea.toUpperCase(); return results.filter(res => { // Check postalAddress.administrativeArea if (res.postalAddress?.administrativeArea === target) { return true; } // Check addressComponents for any administrative area level return res.addressComponents?.some(c => { const isAdmin = c.types?.some(t => t.startsWith('administrative_area_level_')); return isAdmin && c.shortText === target; }); }); } // Example usage: // const filtered = filterByAdminArea(v4Response.results, 'CA');
郵便番号でフィルタ
リクエストの address.postalCode と各結果の postalAddress.postalCode を照合します。比較する前に、入力郵便番号と結果の郵便番号の両方を正規化する必要があります。正規化ロジックはリージョンに大きく依存します。基本的なアプローチとしては、スペースとハイフンを削除し、一貫した大文字と小文字に変換します。
郵便番号の接頭辞(英国の「L2」など)や接尾辞(米国の郵便番号の「+4」など)を処理するには、より高度な正規化が必要になる場合があります。必要な正規化ロジックは、国や郵便番号の形式によって異なります。提供されている正規化関数を調整するか、ターゲットとする地域向けに、より高度なロジックを実装する必要があるかもしれません。
提供されている例では、米国の郵便番号を処理し、ZIP+4 が提供または返された場合でも、5 桁のベースで一致させることができます。
Python コードの例(米国の郵便番号に焦点を当てたもの)
import re def normalize_postal_code_us(pc): # Basic normalization for US: uppercase, alphanumeric only if not pc: return "" normalized = re.sub(r'[^A-Z0-9]', '', pc.upper()) # Return only the first 5 digits for US ZIP codes return normalized[:5] def filter_by_postal_code_us(results, postal_code): normalized_input = normalize_postal_code_us(postal_code) if not normalized_input: return [] filtered_results = [] for res in results: pa_pc = res.get('postalAddress', {}).get('postalCode', '') if normalize_postal_code_us(pa_pc) == normalized_input: filtered_results.append(res) return filtered_results # Example usage: # Matches '94043', '94043-1351', '940431351' # filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043') # filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043-1234')
Node.js コードの例(米国の郵便番号に焦点を当てたもの)
function normalizePostalCodeUs(pc) { // Basic normalization for US: uppercase, alphanumeric only const normalized = (pc || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); // Return only the first 5 digits for US ZIP codes return normalized.substring(0, 5); } function filterByPostalCodeUs(results, postalCode) { const normalizedInput = normalizePostalCodeUs(postalCode); if (!normalizedInput) { return []; } return results.filter(res => { const paPc = res.postalAddress?.postalCode || ''; return normalizePostalCodeUs(paPc) === normalizedInput; }); } // Example usage: // Matches '94043', '94043-1351', '940431351' // const filtered = filterByPostalCodeUs(v4Response.results, '94043'); // const filtered = filterByPostalCodeUs(v4Response.results, '94043-1234');
v3 リバース ジオコーディングから移行する
v3 リバース ジオコーディングを使用して座標を住所に変換している場合は、GET リクエストを受け入れる v4 の場所をリバース ジオコーディングするメソッドに移行する必要があります。
v4 API では、いくつかのパラメータの名前、構造、サポートが変更されています。フィールド マスクを使用して、レスポンスで返すフィールドを指定することを強くおすすめします。
リクエスト パラメータの変更
| v3 パラメータ | v4 パラメータ | メモ |
|---|---|---|
language |
languageCode |
名前を変更しました。省略した場合、v3 では Accept-Language ヘッダーが使用されるか、デフォルトで en が使用されます。一方、v4 では、デフォルトでその場所の現地の言語と文字が使用されます。 |
region |
regionCode |
名前を変更しました。省略すると、v3 のデフォルトは us になりますが、v4 にはデフォルト値がありません。 |
result_type |
types |
名前を変更。繰り返しクエリ パラメータを使用します。 |
location_type |
granularity |
名前を変更。繰り返しクエリ パラメータを使用します。 |
extra_computations |
削除済み | SearchDestinations メソッドに置き換えられました。 |
レスポンス フィールドの変更
| v3 フィールド | v4 フィールド | メモ |
|---|---|---|
status、error_message |
削除済み | v4 では HTTP ステータス コードとエラー本文が使用されます。 |
results.address_components.long_name / results.address_components.short_name |
results.addressComponents.longText / results.addressComponents.shortText |
名前を変更しました。 |
results.geometry.location_type |
results.granularity |
名前を変更しました。 |
results.geometry.location |
results.location |
フィールド名: lat/lng -> latitude/longitude。 |
results.geometry.viewport |
results.viewport |
フィールド名: northeast/southwest -> high/low。 |
| 新機能 | results.addressComponents.languageCode |
特定のアドレス コンポーネントの言語。 |
| 新機能 | results.bounds |
high / low を使用した明示的な境界。 |
| 新機能 | results.place |
場所のリソース名。 |
| 新機能 | results.postalAddress |
構造化された PostalAddress オブジェクト。 |
v3 Address descriptors から移行する
Geocoding API v3 では、extra_computations=ADDRESS_DESCRIPTORS を渡すと、landmarks[] と areas[] を含む address_descriptor オブジェクトが返されました。Geocoding API v4 では、この機能は SearchDestinations メソッド(POST /v4/geocode/destinations)に置き換えられ、各 Destination オブジェクト内で豊富な空間コンテキストが直接返されます。
次の表に、以前の v3 address_descriptor フィールドと、それに対応する v4 SearchDestinations フィールドを示します。
v3 address_descriptor フィールド |
v4 SearchDestinations フィールド |
移行メモ |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
X-Goog-FieldMask で destinations.landmarks をリクエストします。 |
landmarks[].place_id |
landmarks[].place.placeId |
place(PlaceView)オブジェクト内にラップされます。 |
landmarks[].display_name |
landmarks[].place.displayName |
ローカライズされたテキスト(text と languageCode)。 |
landmarks[].types |
landmarks[].place.types |
場所タイプの文字列の配列。 |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
v4 では、未加工の列挙型(ACROSS_THE_ROAD、AROUND_THE_CORNER)ではなく、ローカライズされた対人可読フレーズ("Across from Central Park" など)が返されます。 |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
lowerCamelCase に変更しました。 |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
lower camelCase に名前を変更しました。 |
areas[](containment 列挙型) |
destinations[].containingPlaces[]、subDestinations[] |
構造階層に最も近い同等のもの: 囲まれた複合施設、キャンパス、モール、建物は、containingPlaces[] と subDestinations[] の構造化された PlaceView オブジェクトとして返されます(structureType は GROUNDS または BUILDING に設定され、オプションで displayPolygon アウトラインが設定されます)。近隣地域 / 地区の近接エリアや、v3 の containment 列挙型(NEAR、WITHIN、OUTSKIRTS)に直接対応する代替手段はありません。 |
v3 のプレイス ジオコーディングから移行する
place_id を使用して Geocoding v3 で特定のプレイス ID の住所を取得する場合は、GET リクエストを受け入れる v4 の Place Geocoding メソッドに移行する必要があります。
v4 API では、いくつかのパラメータの名前、構造、サポートが変更されています。フィールド マスクを使用して、レスポンスで返すフィールドを指定することを強くおすすめします。
リクエスト パラメータの変更
| v3 パラメータ | v4 パラメータ | メモ |
|---|---|---|
place_id |
リクエスト proto の place フィールド |
プレイス ID は、パスパラメータ places/{place} として指定されるようになりました(例: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw)。これは、基盤となるリクエストの place フィールドにマッピングされます。 |
language |
languageCode |
名前を変更しました。省略した場合、v3 では Accept-Language ヘッダーが使用されるか、デフォルトで en が使用されます。一方、v4 では、デフォルトでその場所の現地の言語と文字が使用されます。 |
region |
regionCode |
名前を変更しました。省略すると、v3 のデフォルトは us になりますが、v4 にはデフォルト値がありません。 |
レスポンス フィールドの変更
| v3 フィールド | v4 フィールド | メモ |
|---|---|---|
status、error_message |
削除済み | v4 では HTTP ステータス コードとエラー本文が使用されます。 |
results |
(root) | v4 は、results 配列ではなく、単一の結果オブジェクトを返します。 |
results.address_components.long_name / results.address_components.short_name |
addressComponents.longText / addressComponents.shortText |
名前を変更しました。 |
results.geometry.location_type |
granularity |
名前を変更しました。 |
results.geometry.location |
location |
フィールド名: lat/lng -> latitude/longitude。 |
results.geometry.viewport |
viewport |
フィールド名: northeast/southwest -> high/low。 |
results.postcode_localities |
postalCodeLocalities |
名前を変更しました。1 つ以上の地域に対して返されるようになりました(v3 では 1 つ以上が必要)。 |
| 新機能 | addressComponents.languageCode |
特定のアドレス コンポーネントの言語。 |
| 新機能 | bounds |
high / low を使用した明示的な境界。 |
| 新機能 | place |
場所のリソース名。 |
| 新機能 | postalAddress |
構造化された PostalAddress オブジェクト。 |
Geocoding Hyperlocal Data から Destinations に移行する
Geocoding API v3 の次の機能は、Geocoding API v4 の SearchDestinations メソッドに置き換えられます。
- 閲覧開始数
- ナビゲーション ポイント
- 建物の輪郭
- 邸宅と庭園
上記の機能に Geocoding API v3 を使用していた場合は、このドキュメントを参考にして、代わりに SearchDestinations メソッドを使用してこれらの機能を取得してください。このドキュメントでは、SearchDestinations レスポンスでこれらの機能を確認する方法と、Geocoding API v3 と Geocoding API v4 の SearchDestinations メソッドの間で、これらの機能が API レスポンスでどのように表現されるかの違いについて説明します。
閲覧開始数
destination に関連付けられたエントランスを取得するには、destination.entrances フィールドを使用します。
destination.entrances の各 entrance には、次のフィールドがあります(以前の v3 buildings.entrances スキーマを置き換えます)。
displayName- 入口の対人可読名(例:"Gate B")を含む新しいオプション フィールド。location-latitudeとlongitudeを使用したLatLngタイプの場所(v3 のlat/lngを置き換えるもの)。tags- Geocoding API v3 のエントランス(PREFERREDなど)のtagsフィールドと同じです。place- 場所のリソース名(例:places/ChIJ...)。Geocoding API v3 のbuilding_place_idフィールドに代わるものです。v4 では、この場所は建物だけでなく、目的地となる構造物(建物、キャンパス、公園)を表すことができます。
ナビゲーション ポイント
destination に関連付けられたナビゲーション ポイントを取得するには、destination.navigationPoints フィールドを使用します。
destination.navigationPoints の各 navigationPoint には、次のフィールドがあります(以前の v3 navigation_points スキーマを置き換えます)。
navigationPointToken- Routes API のComputeRoutesメソッド(Waypoint.navigationPointToken)で、この特定のナビゲーション ポイントへのルート設定に使用される暗号化されたトークン文字列。ナビゲーション ポイント トークンを使用してルートを設定するをご覧ください。displayName- ナビゲーション ポイントの人が読める形式の名前(例:"5th Ave")を含む新しいオプション フィールド。location-latitudeとlongitudeを使用したLatLngタイプのロケーション。travelModes- Geocoding API v3 のrestricted_travel_modesフィールドに似ていますが、v4 では制限された移動手段ではなく、許容される移動手段(DRIVE、WALK)を指定します。usage- ナビゲーション ポイントでサポートされている到着ユースケース(PICKUP、DROPOFF、PARKINGなど)を指定する新しいフィールド。
建物の輪郭
destination に関連付けられた建物の輪郭を取得するには、建物を表す destination 内の placeView オブジェクトの displayPolygon フィールドを使用します(以前の v3 buildings.building_outlines 配列を置き換えます)。各 placeView について、placeView.structureType フィールドを持つ建物かどうかを確認します。構造タイプが BUILDING の場合、placeView.displayPolygon フィールドからアウトラインを取得できます。placeView には、Geocoding API v3 にはなかった建物の追加フィールドも含まれます。
destination には、次のフィールドに建物を表す placeView オブジェクトを含めることができます。
destination.primary- 目的地の主要な場所。destination.containingPlaces- メインの場所を「含む」より大きな場所を保持する繰り返しフィールド。たとえば、メインの場所がsubpremiseの場合、containingPlacesには通常、建物を表すplaceViewが格納されます。destination.subDestinations- メインの場所のサブ目的地(建物内の個々のアパートメント ユニットやスイートなど)を保持する繰り返しフィールド。
placeView.displayPolygon の形式は、Geocoding API v3 の建物のアウトライン形式(GeoJSON 形式、RFC 7946 形式を使用)と一致します。
邸宅と庭園
建物の外形と同様に、destination に関連付けられた敷地を取得するには、敷地を表す destination 内の placeView オブジェクトの displayPolygon フィールドを使用します(以前の v3 grounds 配列を置き換えます)。各 placeView について、placeView.structureType フィールドを持つ敷地ポリゴンかどうかを確認します。構造タイプが GROUNDS の場合、placeView.displayPolygon フィールドからアウトラインを取得できます。placeView には、Geocoding API v3 にはなかった敷地に関する追加のフィールドも含まれます。
destination には、次のフィールドに敷地を表す placeView オブジェクトを含めることができます。
destination.primarydestination.containingPlacesdestination.subDestinations
placeView.displayPolygon の形式は、Geocoding API v3 の敷地外形形式(GeoJSON 形式)と一致します。この形式では、RFC 7946 形式が使用されます。
結果の精度
Geocoding API v3 では、レスポンス ジオメトリの location_type フィールドに結果の精度が示され、一部のクライアントはこれらの値(ROOFTOP、RANGE_INTERPOLATED、GEOMETRIC_CENTER、APPROXIMATE)に基づいて結果をランク付けまたはフィルタしていました。標準の Geocoding API v4 移行では、このフィールドの名前が granularity に変更されます。
Destinations API(v4 SearchDestinations)には、location_type フィールドはありません。代わりに、空間情報は次のように処理されます。
- クライアントサイドでの手動フィルタリングが不要: 標準のジオコーディングでは、さまざまな粒度で複数の結果が返されますが、
SearchDestinationsメソッドでは、可能な限り最適化された単一の目的地に解決することで、あいまいさを最小限に抑えます。これにより、クライアントは場所のタイプでフィルタして最適な結果を判断する必要がなくなります。 - 構造タイプと表示ポリゴンで表される空間情報:
空間の形状と構造は、以下によって示されます。
displayPolygon(正確なジオメトリ用)。placeViewオブジェクト内のstructureTypeフィールド。
- 構造タイプのマッピング:
POINT、BUILDING、SECTIONのstructureTypeは、通常、以前にROOFTOPと呼ばれていたものに対応します。GROUNDSのstructureTypeは、通常GEOMETRIC_CENTERに対応します。
フィールド マスクを使用してこれらの機能をリクエストする
SearchDestinations メソッドには、返すフィールドを選択するで説明されているように、フィールド マスクが必要です。フィールド マスクを * に設定すると、すべてのフィールドが返されます。また、受信する特定のフィールドに設定することもできます。たとえば、次の API リクエストでは、目的地の入口、ナビゲーション ポイント、建物の輪郭、敷地を取得するために必要なすべてのフィールドを受け取るようにフィールド マスクを設定しています。
curl -X POST -d '{"place": "places/ChIJG3kh4hq6j4AR_XuFQnV0_t8"}' \
-H "X-Goog-Api-Key: API_KEY" \
-H "Content-Type: application/json" \
-H "X-Goog-FieldMask: destinations.entrances,destinations.navigationPoints,destinations.primary,destinations.containingPlaces,destinations.subDestinations" \
https://geocode.googleapis.com/v4/geocode/destinations
一般的な移行レシピとコードパターン
Geocoding v3 または Geocoding++ から SearchDestinations に複雑なワークフローを移行する場合は、次のコードレシピを使用して、一般的な空間構造と住所構造を抽出します。
最適な建物のポリゴンを抽出する
場所または目的地の建物の輪郭をレンダリングする場合:
primaryの場所にstructureType === 'BUILDING'があり、displayPolygonが含まれているかどうかを確認します。- そうでない場合は、
containingPlacesを調べて、囲んでいる建物を見つけます(主な目的地が大きな建物のサブ目的地である場合に便利です)。 - 囲いのある建物が見つからない場合は、
subDestinationsを確認して、個々の建物がリストされているかどうかを確認します。
Python コードの例
def get_best_building_polygon(destination): primary = destination.get('primary', {}) if primary.get('structureType') == 'BUILDING' and 'displayPolygon' in primary: return primary['displayPolygon'] # Check containing places for the parent building for place in destination.get('containingPlaces', []): if place.get('structureType') == 'BUILDING' and 'displayPolygon' in place: return place['displayPolygon'] # Fallback to sub-destinations if available for place in destination.get('subDestinations', []): if place.get('structureType') == 'BUILDING' and 'displayPolygon' in place: return place['displayPolygon'] return None
Node.js のコード例
function getBestBuildingPolygon(destination) { const { primary = {}, containingPlaces = [], subDestinations = [] } = destination; if (primary.structureType === 'BUILDING' && primary.displayPolygon) { return primary.displayPolygon; } const parentBuilding = containingPlaces.find( p => p.structureType === 'BUILDING' && p.displayPolygon ); if (parentBuilding) { return parentBuilding.displayPolygon; } const subBuilding = subDestinations.find( p => p.structureType === 'BUILDING' && p.displayPolygon ); return subBuilding?.displayPolygon || null; }
敷地の輪郭を抽出する
集合住宅、企業キャンパス、ショッピング センター、公園の境界線が必要な場合:
primaryの場所が複合施設全体(structureType === 'GROUNDS')を表す場合は、primary.displayPolygonを使用します。primaryの場所が、より大きな複合施設内にある建物または入り口である場合は、containingPlacesで囲まれた敷地を見つけます。
Python コードの例
def get_grounds_polygon(destination): primary = destination.get('primary', {}) if primary.get('structureType') == 'GROUNDS' and 'displayPolygon' in primary: return primary['displayPolygon'] for place in destination.get('containingPlaces', []): if place.get('structureType') == 'GROUNDS' and 'displayPolygon' in place: return place['displayPolygon'] return None
Node.js のコード例
function getGroundsPolygon(destination) { const { primary = {}, containingPlaces = [] } = destination; if (primary.structureType === 'GROUNDS' && primary.displayPolygon) { return primary.displayPolygon; } const groundsPlace = containingPlaces.find( p => p.structureType === 'GROUNDS' && p.displayPolygon ); return groundsPlace?.displayPolygon || null; }
住所表示とラストマイル到着のランドマークを選択する
ジオコーディング v3 address_descriptor が spatial_relationship 列挙型(WITHIN、BESIDE、BEHIND、NEAR、ACROSS_THE_ROAD、AROUND_THE_CORNER)を返しました。SearchDestinations 内:
- 未加工の関係列挙型はありません。代わりに、
relationalDescription.textを直接使用してください。これには、"Across from Central Park"や"Behind the convention center"など、ローカライズされた表示可能なフレーズが含まれています。"Near "を手動で先頭に追加しないでください。 tagsを使用して、ユースケースに適したランドマークを選択します。ARRIVAL: 目的地のすぐ隣、向かい、または通りを挟んだ向かいにある、地域密着型のランドマーク(通常は 50 ~ 100 メートル以内)。ドライバーのリアルタイムの到着、宅配便の配達確認、アプリ内の到着カードに最適です。ADDRESS: 周辺地域(通常は 100 ~ 500 メートル以内)で、地域的に有名なランドマーク。顧客向けのチェックアウト、注文の確認、乗車前の目的地の曖昧さ回避に最適です。- ランドマークに
ADDRESSタグとARRIVALタグの両方が付いている場合、そのランドマークは近隣でよく知られており、目的地に隣接しています。
Python コードの例
def get_best_relational_landmark(destination, is_last_mile=True): """Select the best landmark based on user context. Args: destination: Destination object from SearchDestinations. is_last_mile: True for arrival and delivery guidance (prefers ARRIVAL tags). False for address display and disambiguation (prefers ADDRESS tags). Returns: Dict with landmark description, distances, tags, and placeId, or None. """ landmarks = destination.get('landmarks', []) if not landmarks: return None target_tag = 'ARRIVAL' if is_last_mile else 'ADDRESS' # Landmarks are ranked by relevance and proximity. Select the first candidate matching the target tag. for lm in landmarks: tags = lm.get('tags', []) if target_tag in tags or ('ARRIVAL' in tags and 'ADDRESS' in tags): description = lm.get('relationalDescription', {}).get('text') if description: return { 'description': description, 'travelDistanceMeters': lm.get('travelDistanceMeters'), 'straightLineDistanceMeters': lm.get('straightLineDistanceMeters'), 'tags': tags, 'placeId': lm.get('place', {}).get('placeId') } # Fallback to the first available landmark with a relational description if no tagged match is found for lm in landmarks: description = lm.get('relationalDescription', {}).get('text') if description: return { 'description': description, 'travelDistanceMeters': lm.get('travelDistanceMeters'), 'straightLineDistanceMeters': lm.get('straightLineDistanceMeters'), 'tags': lm.get('tags', []), 'placeId': lm.get('place', {}).get('placeId') } return None
Node.js のコード例
/** * Select the best landmark based on user context. * * @param {Object} destination Destination object from SearchDestinations. * @param {boolean} [isLastMile=true] True for arrival and delivery guidance * (prefers ARRIVAL tags). False for address display and disambiguation * (prefers ADDRESS tags). * @return {Object|null} */ function getBestRelationalLandmark(destination, isLastMile = true) { const landmarks = destination.landmarks || []; if (!landmarks.length) return null; const targetTag = isLastMile ? 'ARRIVAL' : 'ADDRESS'; // Landmarks are ranked by relevance and proximity. Select the first candidate matching the target tag. const match = landmarks.find((lm) => { const tags = lm.tags || []; return (tags.includes(targetTag) || (tags.includes('ARRIVAL') && tags.includes('ADDRESS'))) && lm.relationalDescription?.text; }) || landmarks.find((lm) => lm.relationalDescription?.text); if (match) { return { description: match.relationalDescription.text, travelDistanceMeters: match.travelDistanceMeters, straightLineDistanceMeters: match.straightLineDistanceMeters, tags: match.tags || [], placeId: match.place?.placeId || null, }; } return null; }
車両のナビゲーション ポイントと優先エントランスへのルート
ラスト ワンマイルのディスパッチと到着のワークフローでは、2 種類の空間アクセス ポイントを組み合わせて使用します。
- ターンバイターン方式の運転:
navigationPointsを使用して、指定された道路の降車ポイントに車両をルーティングします。ナビゲーション ポイントは、近接性と関連性によって事前にランク付けされているため、目的の移動手段('DRIVE'など)と使用タグ('DROPOFF'や'PICKUP'など)を持つ最初の候補が、最適な車両ウェイポイントになります。そのnavigationPointTokenを Routes API のComputeRoutesメソッド(Waypoint.navigationPointToken)または Navigation SDK に送信します。道路にスナップされた運転ポイントが存在しない場合は、建物の入り口または主要な重心にフォールバックします。 - 物理的なドアウェイ アクセス:
destinations.entrancesを使用して、徒歩の配達員または乗客を建物の入り口に案内します。'PREFERRED'のtagsを確認して、直接物理的にアクセスできる可能性が高い入り口を見つけます。入口データが利用できない場合は、歩行者ナビゲーション ポイント('WALK'を含むtravelModes)または主要な重心にフォールバックします。
Python コードの例
def get_routing_and_arrival_points(destination, usage_tag=None): navigation_points = destination.get('navigationPoints', []) entrances = destination.get('entrances', []) primary_location = destination.get('primary', {}).get('location') # 1. Doorstep / Physical Entrance # Prefer PREFERRED entrance -> any entrance -> WALK nav point -> primary location preferred_entrance = None for ent in entrances: if 'PREFERRED' in ent.get('tags', []): preferred_entrance = ent break if not preferred_entrance and entrances: preferred_entrance = entrances[0] walk_nav_point = None for np in navigation_points: if 'WALK' in np.get('travelModes', []): walk_nav_point = np break if preferred_entrance: doorstep_location = preferred_entrance.get('location') elif walk_nav_point: doorstep_location = walk_nav_point.get('location') else: doorstep_location = primary_location # 2. Vehicle Routing Waypoint # Find a driving navigation point. If usage_tag (such as 'DROPOFF' or 'PICKUP') # is specified, prioritize a candidate with that usage tag; otherwise fall back # to the first available driving point. drive_nav_point = None fallback_drive_point = None for np in navigation_points: if 'DRIVE' in np.get('travelModes', []): if usage_tag and usage_tag in np.get('usages', []): drive_nav_point = np break # Exact match for desired usage tag elif fallback_drive_point is None: fallback_drive_point = np # First driving point as fallback if not drive_nav_point: drive_nav_point = fallback_drive_point if drive_nav_point: vehicle_location = drive_nav_point.get('location') nav_token = drive_nav_point.get('navigationPointToken') elif preferred_entrance: vehicle_location = preferred_entrance.get('location') nav_token = None else: vehicle_location = primary_location nav_token = None return { 'vehicleRoutingWaypoint': { 'navigationPointToken': nav_token, 'location': vehicle_location, }, 'doorstepLocation': doorstep_location, }
Node.js のコード例
function getRoutingAndArrivalPoints(destination, usageTag = null) { const navigationPoints = destination.navigationPoints || []; const entrances = destination.entrances || []; const primaryLocation = destination.primary?.location || null; // 1. Doorstep / Physical Entrance const preferredEntrance = entrances.find(ent => ent.tags?.includes('PREFERRED')) || entrances[0] || null; const walkNavPoint = navigationPoints.find(np => np.travelModes?.includes('WALK')) || null; const doorstepLocation = preferredEntrance?.location || walkNavPoint?.location || primaryLocation; // 2. Vehicle Routing Waypoint // Find a driving navigation point. If usageTag (such as 'DROPOFF' or 'PICKUP') // is specified, prioritize a candidate with that usage tag; otherwise fall back // to the first available driving point. const driveNavPoint = (usageTag && navigationPoints.find(np => np.travelModes?.includes('DRIVE') && np.usages?.includes(usageTag))) || navigationPoints.find(np => np.travelModes?.includes('DRIVE')) || null; let vehicleLocation = primaryLocation; let navToken = null; if (driveNavPoint) { vehicleLocation = driveNavPoint.location; navToken = driveNavPoint.navigationPointToken; } else if (preferredEntrance) { vehicleLocation = preferredEntrance.location; } return { vehicleRoutingWaypoint: { navigationPointToken: navToken, location: vehicleLocation, }, doorstepLocation: doorstepLocation, }; }
セキュリティ上の考慮事項
Geocoding API v4 は、サーバー間 API として設計されています。JavaScript ユーザーが v3 から v4 に直接移行する方法はありません。API キーを使用してクライアントサイドの JavaScript(ブラウザなど)から v4 メソッドを直接呼び出すと、API キーが盗難や不正使用のリスクにさらされます。
HTTP リファラー制限は有用ですが、リクエストの Referer ヘッダーを偽造する攻撃者によって簡単にバイパスされる可能性があるため、ウェブサービス エンドポイントの保護としては不十分です。
おすすめの方法
Geocoding API v4 は、独自のバックエンド サーバーから使用することをおすすめします。クライアント アプリケーションは、この中間サーバーにリクエストを送信する必要があります。中間サーバーは、保護された API キー(環境変数や Secret Manager に保存されているキーなど)を使用して Google API を安全に呼び出します。これにより、API キーがフロントエンド コードで公開されることがなくなります。
クライアントサイドのニーズに対応する代替手段
ジオコーディングを必要とするクライアント側のニーズがある場合は、既存のクライアント側ソリューションのいずれかを使用することを検討してください。
- Maps JavaScript API のジオコーディング サービス: ジオコーディング サービスは引き続き v3 バックエンドを使用し、ブラウザ環境での使用を想定して設計されています。
- Places UI キット: 住所関連のユーザー インターフェース要素には、Place Autocomplete 要素を含む Places UI キットを使用します。