Geocoding API v4 چندین روش جدید معرفی میکند که جایگزین عملکرد در نسخه ۳ این API میشود. این راهنما به شما نشان میدهد که چگونه برنامه خود را برای استفاده از روشهای جدید v4 منتقل کنید.
میتوانید از کلیدهای میانای برنامهسازی کاربردی موجودتان با روشهای جدید نسخه ۴ استفاده کنید. بااینحال، اگر درخواست افزایش سهمیه برای نسخه ۳ میانای برنامهسازی کاربردی دادهاید، باید برای میانای برنامهسازی کاربردی نسخه ۴ جدید هم درخواست افزایش سهمیه بدهید.
انتقال از «زمینکدیابی مستقیم» نسخه ۳
اگر از v3 Geocoding برای زمینکدیابی نشانیها استفاده میکنید، باید به روش v4 Geocode an address مهاجرت کنید که درخواست GET را میپذیرد.
v4 API نامها، ساختار، و پشتیبانی از چندین پارامتر را تغییر میدهد. اکیداً توصیه میکنیم که از ماسک فیلد استفاده کنید تا فیلدهایی را که میخواهید در پاسخ برگردانده شوند مشخص کنید.
درخواست تغییر پارامتر
| پارامتر نسخه ۳ | پارامتر v4 | یادداشتها |
|---|---|---|
address، components |
address |
نشانی بدون ساختار (v3 address) اکنون در مسیر نشانی وب ارسال میشود. عناصر نشانی ساختاریافته (v3 components) میتوانند بهعنوان پارامترهای پُرسمان address.* منتقل شوند. بازتولید فیلترهای مؤلفه نسخه ۳ را ببینید. |
bounds |
locationBias.rectangle |
تغییر نام داده شد؛ ساختار به شیء تغییر کرد. |
language |
languageCode |
نام تغییر کرد. وقتی حذف شود، نسخه ۳ از سرصفحه Accept-Language استفاده میکند یا بهطور پیشفرض به en میرود، درحالیکه نسخه ۴ بهطور پیشفرض به زبان محلی و نویسه مکان میرود. |
region |
regionCode |
نام تغییر کرد. وقتی حذف شود، v3 بهطور پیشفرض روی us قرار میگیرد، درحالیکه v4 مقدار پیشفرض ندارد. |
extra_computations |
برداشته شد | با روش SearchDestinations جایگزین شده است. |
تغییرات فیلد پاسخ
| فیلد نسخه ۳ | فیلد v4 | یادداشتها |
|---|---|---|
status، error_message |
برداشته شد | نسخه ۴ از رمزهای وضعیت 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 |
نام تغییر کرد. اکنون برای یک یا چند محل برگردانده شده است (نسخه ۳ باید بیشتر از ۱ باشد). |
results.partial_match |
برداشته شد | |
| جدید | results.addressComponents.languageCode |
زبان مؤلفه نشانی خاص. |
| جدید | results.bounds |
Explicit bounds using high/low. |
| جدید | results.place |
نام منبع برای مکان. |
| جدید | results.postalAddress |
شیء PostalAddress ساختاریافته. |
Reproduce v3 component filters
«زمینکدیابی پیشرو» در «زمینکدیابی» نسخه ۳ شامل پارامتر components بود که
فیلتر کردن سخت نتایج را برای مؤلفههای خاص (مثلاً
components=country:US) فعال میکرد. «زمینکدیابی پیشرو» در نسخه ۴ از این نوع
فیلتر کردن سخت در پارامترهای درخواست پشتیبانی نمیکند. در نسخه ۴، میتوانید اطلاعات نشانی را بهصورت یک رشته غیرساختاریافته در مسیر یا بهصورت پارامترهای پُرسمان ساختاریافته مانند address.addressLines، address.locality، address.administrativeArea، address.postalCode، و address.regionCode ارائه دهید.
پارامترهای ساختاریافته بهعنوان فیلترهای سخت عمل نمیکنند. درعوض، همه مؤلفههای ارائهشده باهم ترکیب میشوند تا نشانی کاملی را تشکیل دهند که میانای برنامهسازی کاربردی تلاش میکند زمینکدیابی کند. میانای برنامهسازی کاربردی بهترین مطابقت را برای کل نشانی مشخصشده
در همه مؤلفهها جستجو میکند. ارائه مؤلفهها بهصورت ساختاریافته میتواند به میانای برنامهسازی کاربردی کمک کند
تا هدف را بهتر درک کند، بهویژه زمانی که اطلاعات نشانی از فیلدهای فرم جداگانه جمعآوری میشود. این کار میتواند به میانای برنامهسازی کاربردی کمک کند تا غلطهای املایی جزئی یا ابهامات موجود در هر مؤلفه را مدیریت کند، زیرا نوع اطلاعات در هر فیلد مشخص است.
برای دستیابی به رفتاری مشابه فیلترهای مؤلفه سخت v3، باید فیلتر کردن سمت کارخواه را در آرایه results که توسط میانای برنامهسازی کاربردی v4 براساس اشیاء postalAddress و addressComponents در پاسخ برگردانده شده است پیادهسازی کنید.
جدول زیر بهترین مطابقت بین فیلترهای components نسخه ۳ و
فیلدهای 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 در درخواست شما با اختصار استاندارد ۲ حرفی ارائه شده باشد. postalAddress.administrativeArea در پاسخ ممکن است بهدلایل مختلفی مستقیماً با پسوندهای کد ISO 3166-2 مطابقت نداشته باشد. اولاً، در برخی مناطق، بخش مربوط به کد ISO 3166-2 بخشی از نمایش استاندارد نشانیهای پستی نیست. برای مثال، در اسپانیا، تقسیمات کشوری سطح ۱ (مثلاً «CN» برای جزایر قناری) ممکن است در addressComponents وجود داشته باشد، اما postalAddress.administrativeArea ممکن است حاوی تقسیمات کشوری سطح ۲ باشد (مثلاً «سانتا کروس د تنریف»). دوم اینکه در برخی مناطق، از مخفف بخش فرعی معمولاً استفاده نمیشود و در postalAddress.administrativeArea با نام طولانیتری نشان داده میشود (به دلایل مشابه، addressComponents.shortText برای مؤلفه نشانی مربوط به بخش فرعی ممکن است با پسوند کد ISO 3166-2 بخش فرعی مطابقت نداشته باشد). علاوهبراین، در برخی موارد ممکن است بخش فرعی در مؤلفه نشانی برای administrative_area_level_n با n بزرگتر از ۱ نشان داده شود.
برای جامعترین نتایج، باید مطابقت را هم در postalAddress.administrativeArea و هم در هر addressComponents با نوع administrative_area_level_n (مثلاً administrative_area_level_1) بررسی کنید.
نمونه کد 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 ارائه یا برگردانده شود.
نمونه کد 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');
انتقال از «زمینکدیابی معکوس» نسخه ۳
اگر از زمینکدیابی معکوس نسخه ۳ برای تبدیل مختصات به نشانی استفاده میکنید، باید به روش زمینکدیابی معکوس مکان نسخه ۴ که درخواست GET را میپذیرد مهاجرت کنید.
v4 API نامها، ساختار، و پشتیبانی از چندین پارامتر را تغییر میدهد. اکیداً توصیه میکنیم که از ماسک فیلد استفاده کنید تا فیلدهایی را که میخواهید در پاسخ برگردانده شوند مشخص کنید.
درخواست تغییر پارامتر
| پارامتر نسخه ۳ | پارامتر v4 | یادداشتها |
|---|---|---|
language |
languageCode |
نام تغییر کرد. وقتی حذف شود، نسخه ۳ از سرصفحه Accept-Language استفاده میکند یا بهطور پیشفرض به en میرود، درحالیکه نسخه ۴ بهطور پیشفرض به زبان محلی و نویسه مکان میرود. |
region |
regionCode |
نام تغییر کرد. وقتی حذف شود، v3 بهطور پیشفرض روی us قرار میگیرد، درحالیکه v4 مقدار پیشفرض ندارد. |
result_type |
types |
تغییر نام داده شد؛ از پارامترهای پُرسمان تکراری استفاده میکند. |
location_type |
granularity |
تغییر نام داده شد؛ از پارامترهای پُرسمان تکراری استفاده میکند. |
extra_computations |
برداشته شد | با روش SearchDestinations جایگزین شده است. |
تغییرات فیلد پاسخ
| فیلد نسخه ۳ | فیلد v4 | یادداشتها |
|---|---|---|
status، error_message |
برداشته شد | نسخه ۴ از رمزهای وضعیت 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 |
Explicit bounds using high/low. |
| جدید | results.place |
نام منبع برای مکان. |
| جدید | results.postalAddress |
شیء PostalAddress ساختاریافته. |
انتقال از توصیفکنندههای نشانی v3
در Geocoding API نسخه ۳، ارسال extra_computations=ADDRESS_DESCRIPTORS یک شیء address_descriptor حاوی landmarks[] و areas[] برمیگرداند. در Geocoding API نسخه ۴، این قابلیت با روش SearchDestinations (POST /v4/geocode/destinations) جایگزین شده است که بافت فضایی غنی را مستقیماً در هر شیء Destination برمیگرداند.
جدول زیر فیلدهای قدیمی v3 address_descriptor را به معادلهای v4 SearchDestinations آنها نگاشت میکند:
فیلد address_descriptor نسخه ۳ |
فیلد SearchDestinations نسخه ۴ |
یادداشتهای انتقال |
|---|---|---|
landmarks[] |
destinations[].landmarks[] |
درخواست destinations.landmarks در X-Goog-FieldMask. |
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 |
بهجای شمارش خام (ACROSS_THE_ROAD، AROUND_THE_CORNER)، نسخه ۴ عبارت بومیسازیشده و قابلخواندن برای انسان (مثلاً "Across from Central Park") را برمیگرداند. |
landmarks[].straight_line_distance_meters |
landmarks[].straightLineDistanceMeters |
به camelCase کوچک تغییر نام یافت. |
landmarks[].travel_distance_meters |
landmarks[].travelDistanceMeters |
به camelCase کوچک تغییر نام یافت. |
areas[] (containment enum) |
destinations[].containingPlaces[] و subDestinations[] |
نزدیکترین معادل موجود برای سلسلهمراتب ساختاری: مجتمعها، پردیسها، مراکز خرید، و ساختمانهای محصور بهعنوان اشیای ساختاریافته PlaceView در containingPlaces[] و subDestinations[] (با structureType تنظیمشده روی GROUNDS یا BUILDING و طرحهای کلی اختیاری displayPolygon) برگردانده میشوند. توجه داشته باشید که هیچ جایگزین مستقیم ۱:۱ برای مناطق مجاور محله/بخش یا شمارش v3 containment (NEAR، WITHIN، OUTSKIRTS) وجود ندارد. |
انتقال از زمینکدیابی مکان v3
اگر از place_id برای دریافت نشانی «شناسه مکان» خاصی با Geocoding
نسخه ۳ استفاده میکنید، باید به روش Geocoding
مکان نسخه ۴ مهاجرت کنید که
درخواست GET را میپذیرد.
v4 API نامها، ساختار، و پشتیبانی از چندین پارامتر را تغییر میدهد. اکیداً توصیه میکنیم که از ماسک فیلد استفاده کنید تا فیلدهایی را که میخواهید در پاسخ برگردانده شوند مشخص کنید.
درخواست تغییر پارامتر
| پارامتر نسخه ۳ | پارامتر v4 | یادداشتها |
|---|---|---|
place_id |
فیلد place در پروتکل درخواست |
«شناسه مکان» اکنون بهعنوان پارامتر مسیر places/{place} ارائه میشود، برای مثال: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw. این مورد به فیلد مکان در درخواست اصلی نگاشت میشود. |
language |
languageCode |
نام تغییر کرد. وقتی حذف شود، نسخه ۳ از سرصفحه Accept-Language استفاده میکند یا بهطور پیشفرض به en میرود، درحالیکه نسخه ۴ بهطور پیشفرض به زبان محلی و نویسه مکان میرود. |
region |
regionCode |
نام تغییر کرد. وقتی حذف شود، v3 بهطور پیشفرض روی us قرار میگیرد، درحالیکه v4 مقدار پیشفرض ندارد. |
تغییرات فیلد پاسخ
| فیلد نسخه ۳ | فیلد v4 | یادداشتها |
|---|---|---|
status، error_message |
برداشته شد | نسخه ۴ از رمزهای وضعیت HTTP و بدنه خطا استفاده میکند. |
results |
(root) | نسخه ۴ یک شیء نتیجه واحد را برمیگرداند، نه آرایه 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 |
نام تغییر کرد. اکنون برای یک یا چند محل برگردانده شده است (نسخه ۳ باید بیشتر از ۱ باشد). |
| جدید | addressComponents.languageCode |
زبان مؤلفه نشانی خاص. |
| جدید | bounds |
Explicit bounds using high/low. |
| جدید | place |
نام منبع برای مکان. |
| جدید | postalAddress |
شیء PostalAddress ساختاریافته. |
انتقال از «دادههای فرامحلی زمینکدیابی» به «مقصدها»
ویژگیهای زیر در Geocoding API v3 با روش SearchDestinations در Geocoding API v4 جایگزین میشوند:
- ورودیها
- نقطههای پیمایش
- طرحهای ساختمان
- محوطه
اگر از Geocoding API v3 برای ویژگیهای بالا استفاده میکردید، از این سند
برای کمک به استفاده از روش SearchDestinations بهجای آن برای دریافت این ویژگیها استفاده کنید.
این سند توضیح میدهد که این ویژگیها را در کجای پاسخ SearchDestinations پیدا کنید و تفاوتهای نحوه نمایش این ویژگیها در پاسخهای میانای برنامهسازی کاربردی بین Geocoding API v3 و روش SearchDestinations Geocoding API v4 را شرح میدهد.
ورودیها
برای دریافت ورودیهای مرتبط با
destination،
از فیلد destination.entrances استفاده کنید.
هر entrance
در destination.entrances فیلدهای زیر را دارد (جایگزین طرحواره قدیمی v3 buildings.entrances):
displayName- فیلد اختیاری جدیدی که حاوی نامی قابلخواندن برای انسان برای ورودی است، برای مثال"Gate B".location- مکانی از نوعLatLngبااستفاده ازlatitudeوlongitude(جایگزین کردن v3lat/lng).tags- همانند فیلدtagsاز ورودیهای Geocoding API v3 (مانندPREFERRED).place- نام منبع مکان (برای مثال،places/ChIJ...)، جایگزین فیلدbuilding_place_idاز Geocoding API v3. در نسخه ۴، این مکان میتواند نشاندهنده هر ساختار مقصدی (ساختمان، پردیس، یا پارک) باشد، نه فقط ساختمان.
نقطههای پیمایش
برای دریافت نقاط ناوبری مرتبط با destination، از فیلد
destination.navigationPoints استفاده کنید.
هر navigationPoint
در destination.navigationPoints فیلدهای زیر را دارد (جایگزین طرحواره قدیمی v3 navigation_points):
navigationPointToken- رشته رمزگذاریشدهای از کد که برای مسیریابی به این نقطه ناوبری خاص در روشComputeRoutesRoutes API (Waypoint.navigationPointToken) استفاده میشود. مسیریابی بااستفاده از کدهای نقطه ناوبری را ببینید.displayName- فیلد اختیاری جدیدی که حاوی نامی قابلخواندن برای انسان برای نقطه ناوبری است، برای مثال"5th Ave".location- مکانی از نوعLatLngبااستفاده ازlatitudeوlongitude.travelModes- مشابه فیلدrestricted_travel_modesاز Geocoding API v3، با این تفاوت که v4 حالتهای سفر قابلقبول (DRIVE،WALK) را بهجای حالتهای سفر محدودشده مشخص میکند.usage- فیلد جدیدی که موارد استفاده پشتیبانیشده برای رسیدن به نقطه ناوبری را مشخص میکند (مانندPICKUP،DROPOFF، یاPARKING).
طرحهای ساختمان
برای دریافت خطوط پیرامونی ساختمان مرتبط با destination، از فیلد
displayPolygon
اشیاء placeView
در destination که نشاندهنده ساختمانها هستند استفاده کنید (جایگزین آرایه قدیمی 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 نسخه ۳ مطابقت دارد که قالب GeoJSON است و از قالب RFC 7946 استفاده میکند.
محوطه
مشابه طرحهای کلی ساختمان، برای دریافت زمینهای مرتبط با
destination، از فیلد displayPolygon
اشیاء placeView در destination که نشاندهنده زمینها هستند استفاده کنید (جایگزین آرایه قدیمی 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(برای هندسه دقیق).- فیلد
structureTypeدر شیءplaceView.
- نگاشت نوع ساختار:
structureTypePOINT،BUILDING، یاSECTIONمعمولاً با آنچه قبلاًROOFTOPنامیده میشد مطابقت دارد.structureTypeازGROUNDSمعمولاً با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; }
انتخاب نشانگرهای مکان برای نمایش نشانی درمقابل رسیدن به مقصد نهایی
Geocoding 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: نشانهای محلی که بلافاصله در مجاورت، روبهرو، یا آنطرف خیابان مقصد قرار دارند (معمولاً در فاصله ۵۰ تا ۱۰۰ متری). بهترین گزینه برای زمان رسیدن راننده بهصورت همزمان، تأیید تحویل پیک، یا کارتهای رسیدن درونبرنامه.ADDRESS: نشانگرهای مکانی برجسته محلی در محله اطراف (معمولاً در فاصله ۱۰۰ تا ۵۰۰ متری). بهترین گزینه برای تسویهحساب مشتری، مرور سفارش، یا ابهامزدایی مقصد پیشاز سفر.- اگر نشانگر مکانی هم برچسب
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; }
مسیر به نقاط ناوبری خودرو و ورودیهای ترجیحی
گردشهای کاری اعزام و ورود مایل آخر دو نوع مکمل از نقاط دسترسی فضایی را ترکیب میکنند:
- رانندگی گامبهگام: وسایل نقلیه را بااستفاده از
navigationPointsبه نقاط پیاده کردن تعیینشده در جاده هدایت کنید. نقاط ناوبری ازقبل براساس نزدیکی و ارتباط رتبهبندی شدهاند، بنابراین اولین گزینه با حالت سفر (مانند'DRIVE') و برچسب استفاده (مانند'DROPOFF'یا'PICKUP') موردنظر شما، نقطهمسیر بهینه خودرو را ارائه میدهد.navigationPointTokenآن را به روشComputeRoutes(Waypoint.navigationPointToken) در Routes API یا کیت توسعه نرمافزار ناوبری ارسال کنید. اگر نقطه رانندگی منطبق با جاده وجود نداشته باشد، به ورودی ساختمان یا مرکز اصلی برگردید. - دسترسی به در ورودی فیزیکی: پیک پیاده یا مسافر را بااستفاده از
destinations.entrancesبه ورودی ساختمان راهنمایی کنید.tagsرا برای'PREFERRED'بررسی کنید تا ورودیهایی را پیدا کنید که احتمالاً دسترسی فیزیکی مستقیم ارائه میدهند. اگر دادههای ورودی دردسترس نیست، به نقطه ناوبری عابر پیاده (travelModesشامل'WALK') یا مرکز اصلی برگردید.
نمونه کد 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 بهعنوان یک میانای برنامهسازی کاربردی سروربهسرور طراحی شده است. مسیر انتقال مستقیمی برای کاربران جاوا اسکریپت از نسخه ۳ به نسخه ۴ وجود ندارد. فراخوانی روشهای v4 مستقیماً از جاوا اسکریپت سمت کارخواه (برای مثال، در مرورگر) بااستفاده از کلید میانای برنامهسازی کاربردی، کلید میانای برنامهسازی کاربردی شما را درمعرض خطر بالای سرقت و سوءاستفاده قرار میدهد.
محدودیتهای ارجاعدهنده HTTP، هرچند مفید هستند، اما برای محافظت از نقاط پایانی سرویس وب کافی نیستند، زیرا مهاجمان میتوانند بهراحتی با جعل سرصفحه Referer در درخواستهای خود، آنها را دور بزنند.
رویکرد توصیهشده
روش توصیهشده برای استفاده از Geocoding API v4 ازطریق سرور زیرینه خودتان است. برنامه کارخواه شما باید درخواستها را به این سرور واسطه ارسال کند، که سپس بااستفاده از کلید میانای برنامهسازی کاربردی محافظتشده (برای مثال، کلیدی که در متغیر محیطی یا مدیر مخفی ذخیره شده است) بهطور ایمن با Google API تماس میگیرد. این کار تضمین میکند که کلید میانای برنامهسازی کاربردی شما هرگز در کد پیشرو آشکار نشود.
جایگزینهایی برای نیازهای سمت کارخواه
اگر نیازهای سمت کارخواه دارید که به زمینکدیابی نیاز دارند، از یکی از راهحلهای سمت کارخواه موجود استفاده کنید:
- Geocoding Service در Maps JavaScript API: Geocoding Service همچنان از باطن نسخه ۳ استفاده میکند و برای استفاده در محیط مرورگر طراحی شده است.
- کیت میانای کاربر «جاها»: برای عناصر میانای کاربر مرتبط با نشانی، از کیت میانای کاربر «جاها»، ازجمله عناصر تکمیل خودکار جا، استفاده کنید.