انتقال از Geocoding نسخه ۳ به نسخه ۴

توسعه‌دهندگان منطقه اقتصادی اروپا (EEA)

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 (جایگزین کردن v3 lat/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 - رشته رمزگذاری‌شده‌ای از کد که برای مسیریابی به این نقطه ناوبری خاص در روش ComputeRoutes Routes 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.primary
  • destination.containingPlaces
  • destination.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.
  • نگاشت نوع ساختار:
    • structureType POINT، 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، از دستورالعمل‌های کد زیر برای استخراج ساختارهای فضایی و نشانی رایج استفاده کنید.

استخراج بهترین چندضلعی ساختمان

اگر می‌خواهید ردپای ساختمان را برای مکان یا مقصدی رندر کنید:

  1. بررسی کنید آیا مکان primary دارای structureType === 'BUILDING' است و displayPolygon دارد یا نه.
  2. اگر نه، containingPlaces را بررسی کنید تا ساختمان دربرگیرنده را پیدا کنید (وقتی مقصد اصلی مقصد فرعی ساختمان بزرگ‌تری باشد، این کار مفید است).
  3. اگر ساختمان محصورکننده‌ای پیدا نشد، 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;
}

استخراج طرح کلی زمین

اگر به مرز مجتمع آپارتمانی، پردیس شرکتی، مرکز خرید، یا پارک نیاز دارید:

  1. اگر مکان primary نشان‌دهنده کل مجتمع (structureType === 'GROUNDS') است، از primary.displayPolygon استفاده کنید.
  2. اگر مکان 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 تماس می‌گیرد. این کار تضمین می‌کند که کلید میانای برنامه‌سازی کاربردی شما هرگز در کد پیش‌رو آشکار نشود.

جایگزین‌هایی برای نیازهای سمت کارخواه

اگر نیازهای سمت کارخواه دارید که به زمین‌کدیابی نیاز دارند، از یکی از راه‌حل‌های سمت کارخواه موجود استفاده کنید: