Geocoding API phiên bản 4 ra mắt một số phương thức mới thay thế chức năng trong phiên bản 3 của API. Hướng dẫn này trình bày cách di chuyển ứng dụng của bạn để sử dụng các phương thức v4 mới.
Bạn có thể sử dụng các khoá API hiện có với các phương thức v4 mới. Tuy nhiên, nếu đã yêu cầu tăng hạn mức trên phiên bản 3 của API, thì bạn phải yêu cầu tăng hạn mức trên API phiên bản 4 mới.
Di chuyển từ tính năng Mã hoá địa lý xuôi phiên bản 3
Nếu sử dụng Mã hoá địa lý phiên bản 3 để mã hoá địa lý địa chỉ, bạn nên chuyển sang phương thức Mã hoá địa lý địa chỉ phiên bản 4, phương thức này chấp nhận yêu cầu GET.
API phiên bản 4 thay đổi tên, cấu trúc và khả năng hỗ trợ cho một số tham số. Bạn nên sử dụng mặt nạ trường để chỉ định các trường mà bạn muốn trả về trong phản hồi.
Yêu cầu thay đổi tham số
| Tham số v3 | Tham số v4 | Ghi chú |
|---|---|---|
address, components |
address |
Địa chỉ không có cấu trúc (v3 address) hiện được truyền trong đường dẫn URL. Bạn có thể truyền các thành phần địa chỉ có cấu trúc (v3 components) dưới dạng tham số truy vấn address.*. Xem Tái tạo bộ lọc thành phần phiên bản 3. |
bounds |
locationBias.rectangle |
Đã đổi tên; cấu trúc đã thay đổi thành đối tượng. |
language |
languageCode |
Đã đổi tên. Khi bị bỏ qua, phiên bản 3 sẽ sử dụng tiêu đề Accept-Language hoặc mặc định là en, trong khi phiên bản 4 mặc định là ngôn ngữ và chữ viết địa phương của vị trí. |
region |
regionCode |
Đã đổi tên. Khi bị bỏ qua, v3 sẽ mặc định là us, trong khi v4 không có giá trị mặc định. |
extra_computations |
Đã xoá | Được thay thế bằng phương thức SearchDestinations. |
Thay đổi trường phản hồi
| Trường v3 | Trường v4 | Ghi chú |
|---|---|---|
status, error_message |
Đã xoá | v4 sử dụng mã trạng thái HTTP và nội dung lỗi. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Đã đổi tên. |
results.geometry.location_type |
results.granularity |
Đã đổi tên. |
results.geometry.location |
results.location |
Tên trường: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Tên trường: northeast/southwest -> high/low. |
results.postcode_localities |
results.postalCodeLocalities |
Đã đổi tên. Hiện được trả về cho một hoặc nhiều địa phương (v3 yêu cầu >1). |
results.partial_match |
Đã xoá | |
| Mới | results.addressComponents.languageCode |
Ngôn ngữ của thành phần địa chỉ cụ thể. |
| Mới | results.bounds |
Giới hạn rõ ràng bằng high/low. |
| Mới | results.place |
Tên tài nguyên của địa điểm. |
| Mới | results.postalAddress |
Đối tượng PostalAddress có cấu trúc. |
Tái tạo bộ lọc thành phần phiên bản 3
Tính năng Mã hoá địa lý chuyển tiếp trong Mã hoá địa lý phiên bản 3 có một tham số components cho phép lọc nghiêm ngặt kết quả cho các thành phần cụ thể (ví dụ: components=country:US). Tính năng Mã hoá địa lý chuyển tiếp trong phiên bản 4 không hỗ trợ kiểu lọc nghiêm ngặt này trong các tham số yêu cầu. Trong phiên bản 4, bạn có thể cung cấp thông tin địa chỉ dưới dạng một chuỗi không có cấu trúc trong đường dẫn hoặc dưới dạng các tham số truy vấn có cấu trúc như address.addressLines, address.locality, address.administrativeArea, address.postalCode và address.regionCode.
Các tham số có cấu trúc không hoạt động như bộ lọc cứng. Thay vào đó, tất cả các thành phần được cung cấp sẽ được kết hợp để tạo thành địa chỉ hoàn chỉnh mà API sẽ cố gắng mã hoá địa lý. API này tìm kiếm kết quả phù hợp nhất cho toàn bộ địa chỉ được chỉ định trên tất cả các thành phần. Việc cung cấp các thành phần theo cách có cấu trúc có thể giúp API hiểu rõ hơn về ý định, đặc biệt là khi thông tin địa chỉ được thu thập từ các trường biểu mẫu riêng biệt. Điều này có thể hỗ trợ API xử lý các lỗi chính tả nhỏ hoặc sự mơ hồ trong mỗi thành phần, vì loại thông tin trong mỗi trường đều rõ ràng.
Để đạt được hành vi tương tự như bộ lọc thành phần cứng của phiên bản 3, bạn phải triển khai tính năng lọc phía máy khách trên mảng results do API phiên bản 4 trả về dựa trên các đối tượng postalAddress và addressComponents trong phản hồi.
Bảng sau đây cho thấy kết quả phù hợp nhất giữa bộ lọc components phiên bản 3 và trường postalAddress phiên bản 4:
| bộ lọc thành phần phiên bản 3 | trường phản hồi v4 |
|---|---|
country |
postalAddress.regionCode |
postal_code |
postalAddress.postalCode |
administrative_area |
postalAddress.administrativeArea hoặc addressComponents |
Ví dụ về tính năng lọc phía máy khách
Các ví dụ sau đây cho thấy cách lọc kết quả để đạt được hành vi tương tự như tính năng lọc thành phần phiên bản 3 cho các trường được hỗ trợ: quốc gia, khu vực hành chính và mã bưu chính. Bạn không nên lọc theo các trường khác vì không có tiêu chí lọc đáng tin cậy.
Lọc theo quốc gia
So khớp address.regionCode trong yêu cầu của bạn với postalAddress.regionCode trong mỗi kết quả. Xin lưu ý rằng mặc dù API chấp nhận mã vùng viết thường trong yêu cầu, nhưng API luôn trả về mã vùng viết hoa trong phản hồi. Do đó, bạn phải chuẩn hoá dữ liệu đầu vào thành chữ viết hoa trước khi so sánh.
Ví dụ về mã 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')
Ví dụ về mã 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');
Lọc theo khu vực hành chính
So khớp address.administrativeArea trong yêu cầu của bạn với postalAddress.administrativeArea trong mỗi kết quả. Tương tự như mã quốc gia, bạn nên chuẩn hoá dữ liệu đầu vào thành chữ hoa trước khi so sánh. Thông tin này chỉ đáng tin cậy khi administrativeArea trong yêu cầu của bạn được cung cấp bằng chữ viết tắt gồm 2 chữ cái theo tiêu chuẩn. postalAddress.administrativeArea trong phản hồi có thể không khớp trực tiếp với hậu tố mã ISO 3166-2 vì một số lý do. Thứ nhất, ở một số khu vực, phân khu tương ứng với mã ISO 3166-2 không thuộc cách trình bày tiêu chuẩn của địa chỉ bưu chính. Ví dụ: ở Tây Ban Nha, khu vực hành chính cấp 1 (ví dụ: "CN" cho Canarias) có thể có trong addressComponents, nhưng postalAddress.administrativeArea có thể chứa khu vực cấp 2 (ví dụ: "Santa Cruz de Tenerife"). Thứ hai, ở một số khu vực, tên viết tắt của đơn vị hành chính không được sử dụng phổ biến và được thể hiện trong postalAddress.administrativeArea bằng tên dài hơn (vì lý do tương tự, addressComponents.shortText cho thành phần địa chỉ tương ứng với đơn vị hành chính có thể không khớp với hậu tố mã ISO 3166-2 của đơn vị hành chính). Ngoài ra, trong một số trường hợp, đơn vị hành chính cấp dưới có thể được biểu thị tại thành phần địa chỉ cho administrative_area_level_n với n lớn hơn 1.
Để có kết quả toàn diện nhất, bạn nên kiểm tra xem có kết quả trùng khớp trong cả postalAddress.administrativeArea và bất kỳ addressComponents nào có loại administrative_area_level_n (ví dụ: administrative_area_level_1) hay không.
Ví dụ về mã 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')
Ví dụ về mã 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');
Lọc theo mã bưu chính
So khớp address.postalCode trong yêu cầu của bạn với postalAddress.postalCode trong mỗi kết quả. Bạn phải chuẩn hoá cả mã bưu chính đầu vào và mã bưu chính kết quả trước khi so sánh. Logic chuẩn hoá phụ thuộc nhiều vào khu vực. Một phương pháp cơ bản là xoá dấu cách và dấu gạch nối, đồng thời chuyển đổi thành một kiểu viết hoa nhất quán.
Bạn có thể cần chuẩn hoá nâng cao hơn để xử lý tiền tố mã bưu chính (ví dụ: "L2" ở Vương quốc Anh) hoặc hậu tố (ví dụ: "+4" trong mã ZIP của Hoa Kỳ). Logic chuẩn hoá cụ thể cần thiết sẽ khác nhau tuỳ theo quốc gia và định dạng của mã bưu chính liên quan. Bạn có thể cần điều chỉnh các hàm chuẩn hoá được cung cấp hoặc triển khai logic phức tạp hơn cho những khu vực mà bạn đang nhắm đến.
Ví dụ được cung cấp xử lý mã ZIP của Hoa Kỳ và cho phép so khớp trên cơ sở 5 chữ số ngay cả khi mã ZIP + 4 được cung cấp hoặc trả về.
Ví dụ về mã Python (tập trung vào mã ZIP của Hoa Kỳ)
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')
Ví dụ về mã Node.js (tập trung vào mã ZIP của Hoa Kỳ)
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');
Di chuyển từ tính năng Mã hoá địa lý ngược phiên bản 3
Nếu sử dụng tính năng Mã hoá địa lý ngược phiên bản 3 để chuyển toạ độ thành địa chỉ, bạn nên di chuyển sang phương thức Mã hoá địa lý ngược một vị trí phiên bản 4. Phương thức này chấp nhận yêu cầu GET.
API phiên bản 4 thay đổi tên, cấu trúc và khả năng hỗ trợ cho một số tham số. Bạn nên sử dụng mặt nạ trường để chỉ định các trường mà bạn muốn trả về trong phản hồi.
Yêu cầu thay đổi tham số
| Tham số v3 | Tham số v4 | Ghi chú |
|---|---|---|
language |
languageCode |
Đã đổi tên. Khi bị bỏ qua, phiên bản 3 sẽ sử dụng tiêu đề Accept-Language hoặc mặc định là en, trong khi phiên bản 4 mặc định là ngôn ngữ và chữ viết địa phương của vị trí. |
region |
regionCode |
Đã đổi tên. Khi bị bỏ qua, v3 sẽ mặc định là us, trong khi v4 không có giá trị mặc định. |
result_type |
types |
Đã đổi tên; sử dụng các tham số truy vấn lặp lại. |
location_type |
granularity |
Đã đổi tên; sử dụng các tham số truy vấn lặp lại. |
extra_computations |
Đã xoá | Được thay thế bằng phương thức SearchDestinations. |
Thay đổi trường phản hồi
| Trường v3 | Trường v4 | Ghi chú |
|---|---|---|
status, error_message |
Đã xoá | v4 sử dụng mã trạng thái HTTP và nội dung lỗi. |
results.address_components.long_name/results.address_components.short_name |
results.addressComponents.longText/results.addressComponents.shortText |
Đã đổi tên. |
results.geometry.location_type |
results.granularity |
Đã đổi tên. |
results.geometry.location |
results.location |
Tên trường: lat/lng -> latitude/longitude. |
results.geometry.viewport |
results.viewport |
Tên trường: northeast/southwest -> high/low. |
| Mới | results.addressComponents.languageCode |
Ngôn ngữ của thành phần địa chỉ cụ thể. |
| Mới | results.bounds |
Giới hạn rõ ràng bằng high/low. |
| Mới | results.place |
Tên tài nguyên của địa điểm. |
| Mới | results.postalAddress |
Đối tượng PostalAddress có cấu trúc. |
Di chuyển từ thông tin mô tả địa chỉ phiên bản 3
Trong Geocoding API phiên bản 3, việc truyền extra_computations=ADDRESS_DESCRIPTORS sẽ trả về một đối tượng address_descriptor chứa landmarks[] và areas[]. Trong Geocoding API phiên bản 4, chức năng này được thay thế bằng phương thức SearchDestinations (POST /v4/geocode/destinations), trả về bối cảnh không gian phong phú ngay trong mỗi đối tượng Destination.
Bảng sau đây liên kết các trường address_descriptor cũ của phiên bản 3 với các trường tương đương của phiên bản 4 SearchDestinations:
Trường address_descriptor phiên bản 3 |
Trường SearchDestinations v4 |
Ghi chú di chuyển |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
Yêu cầu destinations.landmarks trong X-Goog-FieldMask. |
landmarks[].place_id |
landmarks[].place.placeId |
Được gói bên trong đối tượng place (PlaceView). |
landmarks[].display_name |
landmarks[].place.displayName |
Văn bản đã bản địa hoá (text và languageCode). |
landmarks[].types |
landmarks[].place.types |
Mảng chuỗi loại địa điểm. |
landmarks[].spatial_relationship |
landmarks[].relationalDescription |
Thay vì một enum thô (ACROSS_THE_ROAD, AROUND_THE_CORNER), phiên bản 4 trả về một cụm từ đã bản địa hoá, con người có thể đọc được (ví dụ: "Across from Central Park"). |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
Đổi tên thành camelCase viết thường. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
Đổi tên thành camelCase viết thường. |
areas[] (enum containment) |
destinations[].containingPlaces[] và subDestinations[] |
Giá trị tương đương gần nhất có sẵn cho hệ phân cấp cấu trúc: các khu phức hợp, khuôn viên, trung tâm mua sắm và toà nhà bao quanh được trả về dưới dạng đối tượng PlaceView có cấu trúc trong containingPlaces[] và subDestinations[] (với structureType được đặt thành GROUNDS hoặc BUILDING và đường viền displayPolygon không bắt buộc). Xin lưu ý rằng không có giá trị thay thế trực tiếp 1:1 cho các khu vực lân cận/khu vực lân cận hoặc enum v3 containment (NEAR, WITHIN, OUTSKIRTS). |
Di chuyển từ tính năng Mã hoá địa lý địa điểm phiên bản 3
Nếu sử dụng place_id để lấy địa chỉ cho một Mã địa điểm cụ thể bằng Mã hoá địa lý phiên bản 3, bạn phải di chuyển sang phương thức Mã hoá địa lý địa điểm phiên bản 4. Phương thức này chấp nhận yêu cầu GET.
API phiên bản 4 thay đổi tên, cấu trúc và khả năng hỗ trợ cho một số tham số. Bạn nên sử dụng mặt nạ trường để chỉ định các trường mà bạn muốn trả về trong phản hồi.
Yêu cầu thay đổi tham số
| Tham số v3 | Tham số v4 | Ghi chú |
|---|---|---|
place_id |
Trường place trong proto yêu cầu |
Mã địa điểm hiện được cung cấp dưới dạng tham số đường dẫn places/{place}, ví dụ: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. Trường này liên kết với trường địa điểm trong yêu cầu cơ bản. |
language |
languageCode |
Đã đổi tên. Khi bị bỏ qua, phiên bản 3 sẽ sử dụng tiêu đề Accept-Language hoặc mặc định là en, trong khi phiên bản 4 mặc định là ngôn ngữ và chữ viết địa phương của vị trí. |
region |
regionCode |
Đã đổi tên. Khi bị bỏ qua, v3 sẽ mặc định là us, trong khi v4 không có giá trị mặc định. |
Thay đổi trường phản hồi
| Trường v3 | Trường v4 | Ghi chú |
|---|---|---|
status, error_message |
Đã xoá | v4 sử dụng mã trạng thái HTTP và nội dung lỗi. |
results |
(gốc) | v4 trả về một đối tượng kết quả duy nhất, không phải mảng results. |
results.address_components.long_name/results.address_components.short_name |
addressComponents.longText/addressComponents.shortText |
Đã đổi tên. |
results.geometry.location_type |
granularity |
Đã đổi tên. |
results.geometry.location |
location |
Tên trường: lat/lng -> latitude/longitude. |
results.geometry.viewport |
viewport |
Tên trường: northeast/southwest -> high/low. |
results.postcode_localities |
postalCodeLocalities |
Đã đổi tên. Hiện được trả về cho một hoặc nhiều địa phương (v3 yêu cầu >1). |
| Mới | addressComponents.languageCode |
Ngôn ngữ của thành phần địa chỉ cụ thể. |
| Mới | bounds |
Giới hạn rõ ràng bằng high/low. |
| Mới | place |
Tên tài nguyên của địa điểm. |
| Mới | postalAddress |
Đối tượng PostalAddress có cấu trúc. |
Di chuyển từ Dữ liệu mã hoá địa lý theo từng khu vực cụ thể sang Điểm đến
Các tính năng sau đây trong Geocoding API phiên bản 3 đang được thay thế bằng phương thức SearchDestinations của Geocoding API phiên bản 4:
- Số lần truy cập
- Điểm điều hướng
- Đường viền toà nhà
- Vé các hoạt động trong khuôn viên
Nếu bạn đang sử dụng Geocoding API phiên bản 3 cho các tính năng nêu trên, hãy tham khảo tài liệu này để biết cách sử dụng phương thức SearchDestinations để có được các tính năng này.
Tài liệu này giải thích vị trí tìm thấy các tính năng này trong phản hồi SearchDestinations, cũng như sự khác biệt về cách biểu thị các tính năng này trong phản hồi của API giữa Geocoding API phiên bản 3 và phương thức SearchDestinations của Geocoding API phiên bản 4.
Số lần truy cập
Để lấy các lối vào liên kết với một
destination,
hãy sử dụng trường destination.entrances.
Mỗi entrance
trong destination.entrances có các trường sau (thay thế giản đồ buildings.entrances phiên bản 3 cũ):
displayName– một trường tuỳ chọn mới chứa tên mà con người có thể đọc được cho lối vào, ví dụ:"Gate B".location– một vị trí thuộc loạiLatLngsử dụnglatitudevàlongitude(thay thếlat/lngphiên bản 3).tags– giống với trườngtagstừ các lối vào Geocoding API phiên bản 3 (chẳng hạn nhưPREFERRED).place– tên tài nguyên của địa điểm (ví dụ:places/ChIJ...), thay thế trườngbuilding_place_idtrong Geocoding API phiên bản 3. Trong phiên bản 4, địa điểm này có thể đại diện cho bất kỳ cấu trúc điểm đến nào (toà nhà, khuôn viên hoặc công viên), chứ không chỉ toà nhà.
Điểm điều hướng
Để lấy các điểm điều hướng liên kết với một destination, hãy sử dụng trường destination.navigationPoints.
Mỗi navigationPoint
trong destination.navigationPoints có các trường sau (thay thế giản đồ navigation_points phiên bản 3 cũ):
navigationPointToken– một chuỗi mã thông báo đã mã hoá dùng để định tuyến đến điểm điều hướng cụ thể này trong phương thứcComputeRoutescủa Routes API (Waypoint.navigationPointToken). Xem phần Định tuyến bằng mã thông báo điểm điều hướng.displayName– một trường tuỳ chọn mới chứa tên mà con người có thể đọc được cho điểm điều hướng, ví dụ:"5th Ave".location– một vị trí thuộc loạiLatLngsử dụnglatitudevàlongitude.travelModes– tương tự như trườngrestricted_travel_modestrong Geocoding API phiên bản 3, ngoại trừ việc phiên bản 4 chỉ định các phương thức di chuyển được chấp nhận (DRIVE,WALK) thay vì các phương thức di chuyển bị hạn chế.usage– một trường mới chỉ định các trường hợp sử dụng điểm đến được hỗ trợ cho điểm đi theo chỉ dẫn (chẳng hạn nhưPICKUP,DROPOFFhoặcPARKING).
Đường viền toà nhà
Để lấy đường viền toà nhà liên kết với một destination, hãy sử dụng trường displayPolygon của các đối tượng placeView trong destination đại diện cho toà nhà (thay thế mảng buildings.building_outlines phiên bản 3 cũ). Đối với mỗi placeView, hãy kiểm tra xem đó có phải là toà nhà có trường placeView.structureType hay không. Nếu loại cấu trúc là BUILDING, bạn có thể lấy dàn ý từ trường placeView.displayPolygon. placeView cũng sẽ có thêm các trường cho toà nhà không có trong Geocoding API phiên bản 3.
destination có thể có đối tượng placeView đại diện cho một toà nhà trong các trường sau:
destination.primary– địa điểm chính của điểm đến.destination.containingPlaces– một trường lặp lại chứa các địa điểm lớn hơn "chứa" địa điểm chính. Ví dụ: nếu địa điểm chính làsubpremise, thìcontainingPlacesthường chứaplaceViewđại diện cho toà nhà.destination.subDestinations– một trường lặp lại chứa các điểm đến phụ của địa điểm chính (ví dụ: các căn hộ hoặc phòng riêng lẻ trong một toà nhà).
Xin lưu ý rằng định dạng của placeView.displayPolygon khớp với định dạng đường viền toà nhà trong Geocoding API phiên bản 3, tức là định dạng GeoJSON, sử dụng định dạng RFC 7946.
Vé các hoạt động trong khuôn viên
Tương tự như đường viền toà nhà, để lấy khuôn viên liên kết với một destination, hãy sử dụng trường displayPolygon của các đối tượng placeView trong destination đại diện cho khuôn viên (thay thế mảng grounds cũ của phiên bản 3). Đối với mỗi placeView, hãy kiểm tra xem đó có phải là đa giác nền đất có trường placeView.structureType hay không. Nếu loại cấu trúc là GROUNDS, bạn có thể lấy dàn ý từ trường placeView.displayPolygon. placeView cũng sẽ có thêm các trường cho những khu đất không có trong Geocoding API phiên bản 3.
destination có thể có đối tượng placeView đại diện cho một cơ sở trong các trường sau:
destination.primarydestination.containingPlacesdestination.subDestinations
Xin lưu ý rằng định dạng của placeView.displayPolygon khớp với định dạng đường viền khuôn viên trong Geocoding API phiên bản 3, tức là định dạng GeoJSON, sử dụng định dạng RFC 7946.
Độ chính xác của kết quả
Trong Geocoding API phiên bản 3, trường location_type trong hình học phản hồi cho biết độ chính xác của kết quả và một số ứng dụng sẽ xếp hạng hoặc lọc kết quả dựa trên các giá trị này (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER và APPROXIMATE). Trong quá trình di chuyển Geocoding API phiên bản 4 tiêu chuẩn, trường này được đổi tên thành granularity.
Trong Destinations API (phiên bản 4 SearchDestinations), không có trường location_type. Thay vào đó, thông tin không gian được xử lý theo cách khác:
- Không cần lọc thủ công phía máy khách: Mặc dù dịch vụ Mã hoá địa lý tiêu chuẩn cung cấp nhiều kết quả ở nhiều mức độ chi tiết, nhưng phương thức
SearchDestinationsgiảm thiểu sự mơ hồ bằng cách phân giải thành một điểm đến duy nhất, được tối ưu hoá bất cứ khi nào có thể. Nhờ đó, khách hàng không cần phải lọc theo loại vị trí để xác định kết quả phù hợp nhất. - Thông tin không gian được thể hiện bằng loại cấu trúc và đa giác hiển thị:
Hình học và cấu trúc không gian được biểu thị bằng:
displayPolygon(để biết hình học chính xác).- Trường
structureTypetrong đối tượngplaceView.
- Ánh xạ loại cấu trúc:
structureTypecủaPOINT,BUILDINGhoặcSECTIONthường tương ứng với những gì được gọi làROOFTOPtrước đây.structureTypecủaGROUNDSthường tương ứng vớiGEOMETRIC_CENTER.
Sử dụng mặt nạ trường để yêu cầu các tính năng này
Phương thức SearchDestinations yêu cầu một mặt nạ trường, như giải thích trong phần Chọn trường để trả về. Bạn có thể đặt mặt nạ trường thành * để trả về tất cả các trường hoặc bạn có thể đặt mặt nạ trường thành các trường cụ thể mà bạn muốn nhận. Ví dụ: yêu cầu API sau đây đặt mặt nạ trường để nhận tất cả các trường cần thiết nhằm lấy lối vào, điểm đi theo chỉ dẫn, đường viền toà nhà và khuôn viên của một điểm đến:
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
Các mẫu mã và công thức di chuyển phổ biến
Khi di chuyển các quy trình công việc phức tạp từ Geocoding phiên bản 3 hoặc Geocoding++ sang SearchDestinations, hãy sử dụng các công thức mã sau để trích xuất cấu trúc địa chỉ và không gian phổ biến.
Trích xuất đa giác toà nhà phù hợp nhất
Nếu bạn muốn kết xuất dấu chân toà nhà cho một vị trí hoặc điểm đến, hãy làm như sau:
- Kiểm tra xem địa điểm
primarycóstructureType === 'BUILDING'và chứadisplayPolygonhay không. - Nếu không, hãy kiểm tra
containingPlacesđể tìm toà nhà bao quanh (hữu ích khi điểm đến chính là điểm đến phụ của một toà nhà lớn hơn). - Nếu không tìm thấy toà nhà bao quanh, hãy kiểm tra
subDestinationsđể xem các toà nhà riêng lẻ có được liệt kê hay không.
Ví dụ về mã 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
Ví dụ về mã 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; }
Trích xuất đường viền của sân
Nếu bạn cần ranh giới của một khu chung cư, khuôn viên công ty, trung tâm mua sắm hoặc công viên:
- Nếu địa điểm
primaryđại diện cho toàn bộ khu phức hợp (structureType === 'GROUNDS'), hãy sử dụngprimary.displayPolygon. - Nếu địa điểm
primarylà một toà nhà hoặc lối vào nằm bên trong một khu phức hợp lớn hơn, hãy tìm khuôn viên bao quanh trongcontainingPlaces.
Ví dụ về mã 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
Ví dụ về mã 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; }
Chọn địa danh để hiển thị địa chỉ so với điểm đến chặng cuối
Mã hoá địa lý phiên bản 3 address_descriptor đã trả về một enum spatial_relationship (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER). Trong SearchDestinations:
- Không có enum mối quan hệ thô. Thay vào đó, hãy sử dụng trực tiếp
relationalDescription.text. Tệp này chứa các cụm từ đã bản địa hoá, sẵn sàng hiển thị như"Across from Central Park"hoặc"Behind the convention center". Đừng thêm"Near "theo cách thủ công. - Sử dụng
tagsđể chọn mốc phù hợp cho trường hợp sử dụng của bạn:ARRIVAL: Các địa danh theo từng khu vực cụ thể nằm ngay cạnh, đối diện hoặc bên kia đường so với điểm đến (thường trong phạm vi từ 50 đến 100 mét). Phù hợp nhất để thông báo thời gian tài xế đến theo thời gian thực, xác nhận giao hàng của nhân viên giao hàng hoặc thẻ thông báo thời gian đến trong ứng dụng.ADDRESS: Các địa danh nổi tiếng tại địa phương trong khu vực lân cận (thường trong phạm vi từ 100 đến 500 mét). Phù hợp nhất cho quy trình thanh toán dành cho khách hàng, xem xét đơn đặt hàng hoặc làm rõ điểm đến trước chuyến đi.- Nếu một địa danh có cả thẻ
ADDRESSvàARRIVAL, thì địa danh đó vừa nổi tiếng trong khu vực lân cận vừa nằm ngay cạnh điểm đến.
Ví dụ về mã 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
Ví dụ về mã 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; }
Tuyến đường đến các điểm chỉ đường cho xe và lối vào ưu tiên
Quy trình điều phối và đến nơi ở chặng cuối kết hợp hai loại điểm truy cập không gian bổ sung cho nhau:
- Lái xe từng chặng: Định tuyến xe đến các điểm trả khách được chỉ định trên đường bằng
navigationPoints. Các điểm điều hướng được xếp hạng trước theo mức độ gần và mức độ liên quan, vì vậy, điểm đầu tiên có phương thức di chuyển mong muốn (chẳng hạn như'DRIVE') và thẻ sử dụng (chẳng hạn như'DROPOFF'hoặc'PICKUP') sẽ cung cấp điểm tham chiếu tối ưu cho xe. GửinavigationPointTokencủa địa điểm đó đến phương thứcComputeRoutes(Waypoint.navigationPointToken) của Routes API hoặc Navigation SDK. Nếu không có điểm lái xe được điều chỉnh theo đường, hãy quay lại lối vào toà nhà hoặc tâm chính. - Lối vào cửa thực tế: Hướng dẫn nhân viên giao hàng đi bộ hoặc hành khách đến lối vào toà nhà bằng
destinations.entrances. Kiểm tratagscho'PREFERRED'để tìm các lối vào có thể cho phép ra vào trực tiếp. Nếu không có dữ liệu về lối vào, hãy quay lại điểm đi theo chỉ dẫn dành cho người đi bộ (travelModesbao gồm cả'WALK') hoặc tâm chính.
Ví dụ về mã 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, }
Ví dụ về mã 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, }; }
Lưu ý về bảo mật
Geocoding API phiên bản 4 được thiết kế dưới dạng API giữa các máy chủ. Không có lộ trình di chuyển trực tiếp cho người dùng JavaScript từ phiên bản 3 sang phiên bản 4. Việc gọi trực tiếp các phương thức v4 từ JavaScript phía máy khách (ví dụ: trong trình duyệt) bằng khoá API sẽ khiến khoá API của bạn có nguy cơ cao bị đánh cắp và sử dụng sai mục đích.
Các quy định hạn chế về liên kết giới thiệu HTTP, tuy hữu ích, nhưng không đủ để bảo vệ các điểm cuối của dịch vụ web vì kẻ tấn công có thể dễ dàng vượt qua bằng cách giả mạo tiêu đề Referer trong yêu cầu của chúng.
Phương pháp đề xuất
Bạn nên sử dụng Geocoding API phiên bản 4 từ máy chủ phụ trợ của riêng mình. Ứng dụng khách của bạn nên gửi yêu cầu đến máy chủ trung gian này, sau đó máy chủ này sẽ gọi Google API một cách an toàn bằng khoá API được bảo vệ (ví dụ: khoá được lưu trữ trong biến môi trường hoặc trình quản lý bí mật). Điều này đảm bảo rằng khoá API của bạn không bao giờ bị lộ trong mã giao diện người dùng.
Các phương án thay thế cho nhu cầu phía máy khách
Nếu bạn có nhu cầu phía máy khách cần mã hoá địa lý, hãy cân nhắc sử dụng một trong các giải pháp phía máy khách hiện có:
- Dịch vụ mã hoá địa lý trong API Maps JavaScript: Dịch vụ mã hoá địa lý tiếp tục sử dụng phần phụ trợ phiên bản 3 và được thiết kế để sử dụng trong môi trường trình duyệt.
- Places UI Kit: Sử dụng Places UI Kit, bao gồm cả các thành phần của Place Autocomplete, cho các thành phần giao diện người dùng liên quan đến địa chỉ.