Geocoding API w wersji 4 wprowadza kilka nowych metod, które zastępują funkcje interfejsu API w wersji 3. Z tego przewodnika dowiesz się, jak przenieść aplikację, aby korzystała z nowych metod w wersji 4.
Możesz używać istniejących kluczy interfejsu API z nowymi metodami w wersji 4. Jeśli jednak masz prośbę o zwiększenie limitu w wersji 3 interfejsu API, musisz poprosić o zwiększenie limitu w nowych interfejsach API w wersji 4.
Migracja z geokodowania bezpośredniego w wersji 3
Jeśli do geokodowania adresów używasz geokodowania w wersji 3, przejdź na metodę geokodowania adresu w wersji 4, która akceptuje żądanie GET.
W interfejsie API w wersji 4 zmieniono nazwy, strukturę i obsługę kilku parametrów. Zdecydowanie zalecamy użycie maski pola, aby określić pola, które mają zostać zwrócone w odpowiedzi.
Zmiany parametrów żądania
| Parametr v3 | Parametr v4 | Uwagi |
|---|---|---|
address, components |
address |
Nieustrukturyzowany adres (v3 address) jest teraz przekazywany w ścieżce adresu URL. Komponenty uporządkowanego adresu (v3 components) można przekazywać jako parametry zapytania address.*. Zobacz Odtwarzanie filtrów komponentów w wersji 3. |
bounds |
locationBias.rectangle |
Zmieniono nazwę; struktura została zmieniona na obiekt. |
language |
languageCode |
Zmieniono nazwę. Jeśli zostanie pominięty, wersja 3 używa nagłówka Accept-Language lub domyślnie en, a wersja 4 domyślnie używa lokalnego języka i skryptu lokalizacji. |
region |
regionCode |
Zmieniono nazwę. Jeśli zostanie pominięty, w wersji 3 domyślnie przyjmuje wartość us, a w wersji 4 nie ma wartości domyślnej. |
extra_computations |
Usunięto | Zastąpiona przez metodę SearchDestinations. |
Zmiany w polu odpowiedzi
| Pole w wersji 3 | Pole v4 | Uwagi |
|---|---|---|
status, error_message |
Usunięto | Wersja 4 używa kodów stanu HTTP i treści błędów. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Zmieniono nazwę. |
results.geometry.location_type |
results.granularity |
Zmieniono nazwę. |
results.geometry.location |
results.location |
Nazwy pól: lat/lng –> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nazwy pól: northeast/southwest –> high/low. |
results.postcode_localities |
results.postalCodeLocalities |
Zmieniono nazwę. Teraz zwracane dla co najmniej 1 miejscowości (wersja 3 wymaga >1). |
results.partial_match |
Usunięto | |
| Nowość | results.addressComponents.languageCode |
Język konkretnego komponentu adresu. |
| Nowość | results.bounds |
Jawne granice przy użyciu high/low. |
| Nowość | results.place |
Nazwa zasobu miejsca. |
| Nowość | results.postalAddress |
Uporządkowany obiekt PostalAddress. |
Odtwarzanie filtrów komponentów w wersji 3
Geokodowanie bezpośrednie w Geocoding v3 zawierało parametr components, który umożliwiał twarde filtrowanie wyników dla określonych komponentów (np. components=country:US). Geokodowanie bezpośrednie w wersji 4 nie obsługuje tego typu twardego filtrowania w parametrach żądania. W wersji 4 możesz podać informacje o adresie jako pojedynczy nieuporządkowany ciąg znaków w ścieżce lub jako uporządkowane parametry zapytania, takie jak address.addressLines, address.locality, address.administrativeArea, address.postalCode i address.regionCode.
Parametry uporządkowane nie działają jako filtry bezwzględne. Zamiast tego wszystkie podane komponenty są łączone w pełny adres, który interfejs API próbuje zakodować geograficznie. Interfejs API wyszukuje najlepsze dopasowanie dla całego adresu we wszystkich komponentach. Podanie komponentów w uporządkowany sposób może pomóc interfejsowi API lepiej zrozumieć intencję, zwłaszcza gdy informacje o adresie są zbierane z oddzielnych pól formularza. Może to pomóc interfejsowi API w obsłudze drobnych literówek lub niejednoznaczności w poszczególnych komponentach, ponieważ typ informacji w każdym polu jest jasny.
Aby uzyskać działanie podobne do filtrów komponentów twardych w wersji 3, musisz zaimplementować filtrowanie po stronie klienta w tablicy results zwracanej przez interfejs API w wersji 4 na podstawie obiektów postalAddress i addressComponents w odpowiedzi.
W tabeli poniżej znajdziesz najlepsze dopasowanie filtrów components w wersji 3 do pól postalAddress w wersji 4:
| filtr komponentów w wersji 3 | Pole odpowiedzi v4 |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea lub addressComponents |
Przykłady filtrowania po stronie klienta
Poniższe przykłady pokazują, jak filtrować wyniki, aby uzyskać zachowanie podobne do filtrowania komponentów w wersji 3 w przypadku obsługiwanych pól: kraj, region i kod pocztowy. Nie zalecamy filtrowania według innych pól, ponieważ nie ma wiarygodnych kryteriów filtrowania.
Filtruj według kraju
Dopasuj parametr address.regionCode z żądania do parametru postalAddress.regionCode w każdym wyniku. Pamiętaj, że chociaż interfejs API akceptuje w żądaniu kody regionów zapisane małymi literami, w odpowiedzi zawsze zwraca je zapisane wielkimi literami, dlatego przed porównaniem musisz znormalizować dane wejściowe do wielkich liter.
Przykładowy kod w Pythonie
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')
Przykładowy kod w 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');
Filtruj według regionu
Dopasuj parametr address.administrativeArea z żądania do parametru postalAddress.administrativeArea w każdym wyniku. Podobnie jak w przypadku kodów krajów, przed porównaniem należy znormalizować dane wejściowe, aby były zapisane wielkimi literami. Jest to wiarygodne tylko wtedy, gdy parametr administrativeArea w żądaniu jest podany ze standardowym 2-literowym skrótem. Wartość postalAddress.administrativeArea w odpowiedzi może nie odpowiadać bezpośrednio sufiksom kodów ISO 3166-2 z kilku powodów. Po pierwsze, w niektórych obszarach podział odpowiadający kodowi ISO 3166-2 nie jest częścią standardowej reprezentacji adresów pocztowych. Na przykład w Hiszpanii region poziomu 1 (np. „CN” dla Wysp Kanaryjskich) może być obecny w addressComponents, ale postalAddress.administrativeArea może zawierać region poziomu 2 (np. „Santa Cruz de Tenerife”). Po drugie, w niektórych obszarach skrót nazwy podregionu nie jest powszechnie używany i jest reprezentowany w postalAddress.administrativeArea dłuższą nazwą (z podobnych powodów addressComponents.shortText dla komponentu adresu odpowiadającego podregionowi może nie pasować do sufiksu kodu ISO 3166-2 podregionu). W niektórych przypadkach podział może być też reprezentowany w komponencie adresu dla administrative_area_level_n, gdzie n jest większe niż 1.
Aby uzyskać najbardziej wyczerpujące wyniki, sprawdź, czy występuje dopasowanie zarówno w postalAddress.administrativeArea, jak i w dowolnym addressComponents z typem administrative_area_level_n (np. administrative_area_level_1).
Przykładowy kod w Pythonie
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')
Przykładowy kod w 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');
Filtrowanie według kodu pocztowego
Dopasuj parametr address.postalCode z żądania do parametru postalAddress.postalCode w każdym wyniku. Przed porównaniem musisz znormalizować zarówno wejściowe, jak i wynikowe kody pocztowe. Logika normalizacji zależy w dużej mierze od regionu. Podstawowe podejście polega na usunięciu spacji i łączników oraz ujednoliceniu wielkości liter.
W przypadku prefiksów kodów pocztowych (np. „L2” w Wielkiej Brytanii) lub sufiksów (np. „+4” w amerykańskich kodach pocztowych) może być konieczna bardziej zaawansowana normalizacja. Wymagana logika normalizacji będzie się różnić w zależności od kraju i formatów kodów pocztowych. Może być konieczne dostosowanie podanych funkcji normalizacji lub wdrożenie bardziej zaawansowanej logiki dla regionów, na które kierujesz reklamy.
Podany przykład obsługuje kody pocztowe w USA i umożliwia dopasowanie na podstawie 5-cyfrowego kodu, nawet jeśli podany lub zwrócony jest kod ZIP+4.
Przykładowy kod w Pythonie (dotyczący kodów pocztowych w USA)
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')
Przykładowy kod w Node.js (dotyczący kodów pocztowych w USA)
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');
Migracja z odwrotnego geokodowania w wersji 3
Jeśli używasz odwrotnego geokodowania w wersji 3 do przekształcania współrzędnych w adresy, przejdź na metodę odwrotnego geokodowania lokalizacji w wersji 4, która akceptuje żądanie GET.
W interfejsie API w wersji 4 zmieniono nazwy, strukturę i obsługę kilku parametrów. Zdecydowanie zalecamy użycie maski pola, aby określić pola, które mają zostać zwrócone w odpowiedzi.
Zmiany parametrów żądania
| Parametr v3 | Parametr v4 | Uwagi |
|---|---|---|
language |
languageCode |
Zmieniono nazwę. Jeśli zostanie pominięty, wersja 3 używa nagłówka Accept-Language lub domyślnie en, a wersja 4 domyślnie używa lokalnego języka i skryptu lokalizacji. |
region |
regionCode |
Zmieniono nazwę. Jeśli zostanie pominięty, w wersji 3 domyślnie przyjmuje wartość us, a w wersji 4 nie ma wartości domyślnej. |
result_type |
types |
Zmieniono nazwę; używa powtarzających się parametrów zapytania. |
location_type |
granularity |
Zmieniono nazwę; używa powtarzających się parametrów zapytania. |
extra_computations |
Usunięto | Zastąpiona przez metodę SearchDestinations. |
Zmiany w polu odpowiedzi
| Pole w wersji 3 | Pole v4 | Uwagi |
|---|---|---|
status, error_message |
Usunięto | Wersja 4 używa kodów stanu HTTP i treści błędów. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Zmieniono nazwę. |
results.geometry.location_type |
results.granularity |
Zmieniono nazwę. |
results.geometry.location |
results.location |
Nazwy pól: lat/lng –> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Nazwy pól: northeast/southwest –> high/low. |
| Nowość | results.addressComponents.languageCode |
Język konkretnego komponentu adresu. |
| Nowość | results.bounds |
Jawne granice przy użyciu high/low. |
| Nowość | results.place |
Nazwa zasobu miejsca. |
| Nowość | results.postalAddress |
Uporządkowany obiekt PostalAddress. |
Migracja z deskryptorów adresów w wersji 3
W interfejsie Geocoding API v3 przekazanie extra_computations=ADDRESS_DESCRIPTORS zwracało obiekt address_descriptor zawierający landmarks[] i areas[]. W Geocoding API w wersji 4 tę funkcję zastępuje metoda SearchDestinations (POST /v4/geocode/destinations), która zwraca bogaty kontekst przestrzenny bezpośrednio w każdym obiekcie Destination.
W tabeli poniżej znajdziesz mapowanie starszych pól address_descriptor w wersji 3 na ich odpowiedniki w wersji 4 (SearchDestinations):
Pole address_descriptor w wersji 3 |
Pole SearchDestinations w wersji 4 |
Uwagi dotyczące migracji |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
Poproś o destinations.landmarks w X-Goog-FieldMask. |
landmarks[].place_id |
landmarks[].place.placeId |
Są opakowane w obiekt place (PlaceView). |
landmarks[].display_name |
landmarks[].place.displayName |
Zlokalizowany tekst (text i languageCode). |
landmarks[].types |
landmarks[].place.types |
Tablica ciągów znaków typów miejsc. |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
Zamiast nieprzetworzonego typu wyliczeniowego (ACROSS_THE_ROAD, AROUND_THE_CORNER) wersja 4 zwraca zlokalizowane, zrozumiałe dla człowieka wyrażenie (np. "Across from Central Park"). |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
Zmieniono nazwę na lower camelCase. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
Zmieniono nazwę na lower camelCase. |
areas[] (typ wyliczeniowy containment) |
destinations[].containingPlaces[] i subDestinations[] |
Najbliższy dostępny odpowiednik hierarchii strukturalnej: otaczające kompleksy, kampusy, centra handlowe i budynki są zwracane jako obiekty PlaceView w polach containingPlaces[] i subDestinations[] (z polem structureType ustawionym na GROUNDS lub BUILDING i opcjonalnymi konturami displayPolygon). Pamiętaj, że nie ma bezpośredniego odpowiednika 1:1 dla obszarów zbliżonych do dzielnicy/okręgu ani dla typu wyliczeniowego containment w wersji 3 (NEAR, WITHIN, OUTSKIRTS). |
Migracja z geokodowania miejsc w wersji 3
Jeśli używasz place_id, aby uzyskać adres dla konkretnego identyfikatora miejsca za pomocą Geocoding v3, musisz przejść na metodę Place Geocoding w wersji 4, która akceptuje żądanie GET.
W interfejsie API w wersji 4 zmieniono nazwy, strukturę i obsługę kilku parametrów. Zdecydowanie zalecamy użycie maski pola, aby określić pola, które mają zostać zwrócone w odpowiedzi.
Zmiany parametrów żądania
| Parametr v3 | Parametr v4 | Uwagi |
|---|---|---|
place_id |
Pole place w proto żądania |
Identyfikator miejsca jest teraz podawany jako parametr ścieżki places/{place}, na przykład: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Jest ono mapowane na pole miejsca w podstawowym żądaniu. |
language |
languageCode |
Zmieniono nazwę. Jeśli zostanie pominięty, wersja 3 używa nagłówka Accept-Language lub domyślnie en, a wersja 4 domyślnie używa lokalnego języka i skryptu lokalizacji. |
region |
regionCode |
Zmieniono nazwę. Jeśli zostanie pominięty, w wersji 3 domyślnie przyjmuje wartość us, a w wersji 4 nie ma wartości domyślnej. |
Zmiany w polu odpowiedzi
| Pole w wersji 3 | Pole v4 | Uwagi |
|---|---|---|
status, error_message |
Usunięto | Wersja 4 używa kodów stanu HTTP i treści błędów. |
results |
(root) | Wersja 4 zwraca pojedynczy obiekt wynikowy, a nie tablicę results. |
results.address_components.long_name/results.address_components.short_name |
addressComponents.longText/addressComponents.shortText |
Zmieniono nazwę. |
results.geometry.location_type |
granularity |
Zmieniono nazwę. |
results.geometry.location |
location |
Nazwy pól: lat/lng –> latitude/longitude. |
results.geometry.viewport |
viewport |
Nazwy pól: northeast/southwest –> high/low. |
results.postcode_localities |
postalCodeLocalities |
Zmieniono nazwę. Teraz zwracane dla co najmniej 1 miejscowości (wersja 3 wymaga >1). |
| Nowość | addressComponents.languageCode |
Język konkretnego komponentu adresu. |
| Nowość | bounds |
Jawne granice przy użyciu high/low. |
| Nowość | place |
Nazwa zasobu miejsca. |
| Nowość | postalAddress |
Uporządkowany obiekt PostalAddress. |
Migracja z geokodowania hiperlokalnych danych do miejsc docelowych
Te funkcje interfejsu Geocoding API w wersji 3 są zastępowane przez metodę SearchDestinations interfejsu Geocoding API w wersji 4:
- Wejścia
- Punkty nawigacyjne
- Kontury budynków
- Tereny posiadłości
Jeśli do korzystania z powyższych funkcji używasz interfejsu Geocoding API w wersji 3, zapoznaj się z tym dokumentem, aby dowiedzieć się, jak zamiast tego używać metody SearchDestinations.
W tym dokumencie wyjaśniamy, gdzie w odpowiedzi SearchDestinations można znaleźć te funkcje, oraz opisujemy różnice w sposobie ich reprezentowania w odpowiedziach interfejsu API między interfejsem Geocoding API w wersji 3 a metodą SearchDestinations interfejsu Geocoding API w wersji 4.
Wejścia
Aby uzyskać wejścia powiązane z destination, użyj pola destination.entrances.
Każdy element entrance w destination.entrances ma te pola (zastępujące starszy schemat buildings.entrances w wersji 3):
displayName– nowe opcjonalne pole, które zawiera zrozumiałą dla człowieka nazwę wejścia, np."Gate B".location– lokalizacja typuLatLngkorzystająca zlatitudeilongitude(zastępujelat/lngw wersji 3).tags– taki sam jak poletagsz wejść Geocoding API w wersji 3 (np.PREFERRED).place– nazwa zasobu miejsca (np.places/ChIJ...), która zastępuje polebuilding_place_idz interfejsu Geocoding API w wersji 3. W wersji 4 to miejsce może reprezentować dowolną strukturę miejsca docelowego (budynek, kampus lub park), a nie tylko budynek.
Punkty nawigacyjne
Aby uzyskać punkty nawigacyjne powiązane z destination, użyj pola destination.navigationPoints.
Każdy element navigationPoint w destination.navigationPoints ma te pola (zastępujące starszy schemat navigation_points w wersji 3):
navigationPointToken– zaszyfrowany ciąg tokena używany do kierowania do tego konkretnego punktu nawigacyjnego w metodzieComputeRoutesinterfejsu Routes API (Waypoint.navigationPointToken). Zobacz Wyznaczanie trasy za pomocą tokenów punktów nawigacyjnych.displayName– nowe opcjonalne pole, które zawiera zrozumiałą dla człowieka nazwę punktu nawigacyjnego, np."5th Ave".location– lokalizacja typuLatLng, która korzysta zlatitudeilongitude.travelModes– podobne do polarestricted_travel_modesz Geocoding API w wersji 3, z tą różnicą, że w wersji 4 określa akceptowalne środki transportu (DRIVE,WALK), a nie ograniczone środki transportu.usage– nowe pole określające obsługiwane przypadki użycia punktu nawigacyjnego (np.PICKUP,DROPOFFlubPARKING).
Kontury budynków
Aby uzyskać obrysy budynków powiązane z destination, użyj pola displayPolygon obiektów placeView w destination, które reprezentują budynki (zastępując starszą tablicę buildings.building_outlines w wersji 3). W przypadku każdego elementu placeView sprawdź, czy jest to budynek z polem placeView.structureType. Jeśli typ struktury to BUILDING, możesz uzyskać konspekt z pola placeView.displayPolygon. placeView będzie też zawierać dodatkowe pola dotyczące budynku, których nie było w interfejsie Geocoding API w wersji 3.
Obiekt destination może zawierać obiekt placeView, który reprezentuje budynek w tych polach:
destination.primary– główne miejsce w miejscu docelowym.destination.containingPlaces– pole powtarzane, które zawiera większe miejsca „zawierające” miejsce główne. Jeśli na przykład głównym miejscem jestsubpremise,containingPlaceszwykle zawieraplaceViewreprezentujący budynek.destination.subDestinations– pole powtarzane, które zawiera miejsca podrzędne miejsca głównego (np. poszczególne mieszkania lub apartamenty w budynku).
Zwróć uwagę, że format placeView.displayPolygon odpowiada formatowi obrysu budynku w interfejsie Geocoding API w wersji 3, czyli formatowi GeoJSON, który używa formatu RFC 7946.
Tereny posiadłości
Podobnie jak w przypadku obrysów budynków, aby uzyskać tereny powiązane z destination, użyj pola displayPolygon obiektów placeView w destination, które reprezentują tereny (zastępując starszą tablicę grounds w wersji 3). Sprawdź, czy każdy element placeView jest wielokątem terenu z polem placeView.structureType. Jeśli typ struktury to GROUNDS, konspekt możesz pobrać z pola placeView.displayPolygon. placeView będzie też zawierać dodatkowe pola dotyczące terenów, których nie było w interfejsie Geocoding API w wersji 3.
Obiekt destination może zawierać obiekt placeView, który reprezentuje teren w tych polach:
destination.primarydestination.containingPlacesdestination.subDestinations
Zwróć uwagę, że format placeView.displayPolygon odpowiada formatowi konturu terenu w interfejsie Geocoding API w wersji 3, czyli formatowi GeoJSON, który korzysta z formatu RFC 7946.
Precyzja wyników
W Geocoding API w wersji 3 pole location_type w geometrii odpowiedzi wskazywało dokładność wyników, a niektórzy klienci oceniali lub filtrowali wyniki na podstawie tych wartości (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER i APPROXIMATE). W przypadku standardowych migracji do Geocoding API w wersji 4 nazwa tego pola została zmieniona na granularity.
W interfejsie Destinations API (wersja 4 SearchDestinations) nie ma pola location_type. Zamiast tego informacje przestrzenne są przetwarzane w inny sposób:
- Brak konieczności ręcznego filtrowania po stronie klienta: standardowe geokodowanie zapewnia wiele wyników o różnym stopniu szczegółowości, natomiast metoda
SearchDestinationsminimalizuje niejednoznaczność, zwracając w miarę możliwości pojedyncze, zoptymalizowane miejsce docelowe. Dzięki temu klienci nie muszą filtrować wyników według typu lokalizacji, aby określić, który wynik jest najlepszy. - Informacje przestrzenne reprezentowane przez typ struktury i wielokąty wyświetlania:
geometria przestrzenna i struktura są wskazywane przez:
displayPolygon(dokładna geometria).- Pole
structureTypew obiekcieplaceView.
- Mapowanie typu struktury:
structureTypeo wartościPOINT,BUILDINGlubSECTIONzazwyczaj odpowiada temu, co wcześniej nazywanoROOFTOP.- Wartość
structureTypeparametruGROUNDSodpowiada zwykleGEOMETRIC_CENTER.
Używanie maski pola do wysyłania żądań dotyczących tych funkcji
Metoda SearchDestinations wymaga maski pola, jak wyjaśniono w artykule Wybieranie pól do zwrócenia. Aby zwrócić wszystkie pola, możesz ustawić maskę pola na *. Możesz też ustawić ją na konkretne pola, które chcesz otrzymać. Na przykład to żądanie do interfejsu API ustawia maskę pola, aby otrzymywać wszystkie pola wymagane do uzyskania wejść, punktów nawigacyjnych, obrysów budynków i terenów miejsca docelowego:
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
Typowe przepisy na migrację i wzorce kodu
Podczas migracji złożonych przepływów pracy z Geocoding v3 lub Geocoding++ do SearchDestinations użyj tych przepisów na kod, aby wyodrębnić typowe struktury przestrzenne i adresowe.
Wyodrębnij najlepszy wielokąt budynku
Jeśli chcesz wyrenderować obrys budynku dla lokalizacji lub miejsca docelowego:
- Sprawdź, czy miejsce
primarymastructureType === 'BUILDING'i zawieradisplayPolygon. - Jeśli nie, sprawdź
containingPlaces, aby znaleźć budynek, w którym znajduje się miejsce docelowe (przydatne, gdy główne miejsce docelowe jest podrzędnym miejscem docelowym większego budynku). - Jeśli nie znajdziesz budynku nadrzędnego, sprawdź
subDestinations, aby zobaczyć, czy poszczególne budynki są wymienione.
Przykładowy kod w Pythonie
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
Przykładowy kod w 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; }
Wyodrębnij kontur terenu
Jeśli potrzebujesz granicy kompleksu apartamentów, kampusu firmowego, centrum handlowego lub parku:
- Jeśli miejsce
primaryreprezentuje cały kompleks (structureType === 'GROUNDS'), użyjprimary.displayPolygon. - Jeśli miejsce
primaryjest budynkiem lub wejściem znajdującym się w większym kompleksie, znajdź otaczający go teren wcontainingPlaces.
Przykładowy kod w Pythonie
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
Przykładowy kod w 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; }
Wybieranie punktów orientacyjnych do wyświetlania adresu i ostatniego etapu podróży
Geocoding v3 address_descriptor zwrócił typ wyliczeniowy spatial_relationship (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER). W SearchDestinations:
- Brak nieprzetworzonego typu wyliczeniowego relacji. Zamiast tego użyj bezpośrednio
relationalDescription.text. Zawiera zlokalizowane, gotowe do wyświetlenia wyrażenia, takie jak"Across from Central Park"lub"Behind the convention center". Nie dodawaj ręcznie"Near "na początku. - Użyj
tags, aby wybrać odpowiedni punkt orientacyjny dla swojego przypadku użycia:ARRIVAL: hiperlokalne punkty orientacyjne położone bezpośrednio obok miejsca docelowego, naprzeciwko niego lub po drugiej stronie ulicy (zwykle w odległości 50–100 metrów). Najlepiej sprawdza się w przypadku informacji o przyjeździe kierowcy w czasie rzeczywistym, potwierdzenia dostawy przez kuriera lub kart przyjazdu w aplikacji.ADDRESS: lokalne punkty orientacyjne w pobliżu (zwykle w odległości 100–500 metrów). Najlepiej sprawdza się w przypadku płatności, sprawdzania zamówienia lub uściślania miejsca docelowego przed podróżą.- Jeśli punkt orientacyjny ma zarówno tag
ADDRESS, jak iARRIVAL, oznacza to, że jest dobrze znany w okolicy i znajduje się bezpośrednio obok miejsca docelowego.
Przykładowy kod w Pythonie
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
Przykładowy kod w 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; }
wyznaczanie trasy do punktów nawigacji pojazdu i preferowanych wejść;
Przepływy pracy związane z wysyłką i przybyciem na ostatnim odcinku łączą 2 uzupełniające się typy przestrzennych punktów dostępu:
- Szczegółowe wskazówki dojazdu: kieruj pojazdy do wyznaczonych punktów odbioru na drodze za pomocą
navigationPoints. Punkty nawigacyjne są wstępnie uszeregowane według bliskości i trafności, więc pierwszy kandydat z wybranym trybem podróży (np.'DRIVE') i tagiem użytkowania (np.'DROPOFF'lub'PICKUP') zapewnia optymalny punkt na trasie pojazdu. Wyślij jegonavigationPointTokendo metodyComputeRoutesinterfejsu Routes API (Waypoint.navigationPointToken) lub do pakietu Navigation SDK. Jeśli nie ma punktu dojazdu przyciągniętego do drogi, użyj wejścia do budynku lub głównego środka ciężkości. - Dostęp do drzwi wejściowych: poprowadź pieszego kuriera lub pasażera do wejścia do budynku za pomocą
destinations.entrances. Sprawdźtagsdla'PREFERRED', aby znaleźć wejścia, które prawdopodobnie zapewniają bezpośredni dostęp fizyczny. Jeśli nie ma danych o wejściu, użyj punktu nawigacji pieszej (travelModes, w tym'WALK') lub głównego środka ciężkości.
Przykładowy kod w Pythonie
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, }
Przykładowy kod w 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, }; }
Bezpieczeństwo
Interfejs Geocoding API w wersji 4 został zaprojektowany jako interfejs API między serwerami. Nie ma bezpośredniej ścieżki migracji dla użytkowników JavaScriptu z wersji 3 do wersji 4. Wywoływanie metod v4 bezpośrednio z kodu JavaScript po stronie klienta (np. w przeglądarce) przy użyciu klucza interfejsu API naraża ten klucz na kradzież i niewłaściwe użycie.
Ograniczenia dotyczące stron odsyłających HTTP, choć przydatne, nie zapewniają wystarczającej ochrony punktów końcowych usług internetowych, ponieważ mogą zostać łatwo pominięte przez atakujących, którzy sfałszują nagłówek Referer w swoich żądaniach.
Zalecane działania
Zalecanym sposobem korzystania z interfejsu Geocoding API w wersji 4 jest używanie go z własnego serwera backendu. Aplikacja kliencka powinna wysyłać żądania do tego serwera pośredniczącego, który następnie bezpiecznie wywołuje interfejs API Google za pomocą chronionego klucza interfejsu API (np. klucza przechowywanego w zmiennej środowiskowej lub Secret Managerze). Dzięki temu klucz interfejsu API nigdy nie zostanie ujawniony w kodzie frontendu.
Alternatywne rozwiązania po stronie klienta
Jeśli masz potrzeby po stronie klienta, które wymagają geokodowania, rozważ użycie jednego z istniejących rozwiązań po stronie klienta:
- Usługa geokodowania w interfejsie Maps JavaScript API: usługa geokodowania nadal korzysta z backendu w wersji 3 i jest przeznaczona do użytku w środowisku przeglądarki.
- Places UI Kit: używaj Places UI Kit, w tym elementów autouzupełniania miejsc, do tworzenia elementów interfejsu związanych z adresami.