Geocoding v3 থেকে v4-এ মাইগ্রেট করা

ইউরোপীয় অর্থনৈতিক অঞ্চল (EEA)-এর ডেভেলপার

Geocoding API v4-এ বেশ কিছু নতুন পদ্ধতি যোগ করা হয়েছে যা API-এর v3 ভার্সনের ফাংশনকে প্রতিস্থাপন করে। নতুন v4 পদ্ধতি ব্যবহার করার জন্য কীভাবে আপনার অ্যাপ মাইগ্রেট করবেন তা এই নির্দেশিকা থেকে জানতে পারবেন।

আপনি নতুন v4 পদ্ধতির সাথে আগে থেকে থাকা API কী ব্যবহার করতে পারবেন। তবে, আপনি যদি API-এর v3 ভার্সনে কোটা বাড়ানোর অনুরোধ করে থাকেন, তাহলে আপনাকে নতুন v4 API-তে কোটা বাড়ানোর অনুরোধ করতে হবে।

v3 ফরওয়ার্ড জিওকোডিং থেকে মাইগ্রেট করুন

আপনি যদি ঠিকানা জিওকোড করতে v3 জিওকোডিং ব্যবহার করেন, তাহলে আপনাকে v4 ঠিকানা জিওকোড করুন পদ্ধতিতে মাইগ্রেট করতে হবে, যা GET অনুরোধ গ্রহণ করে।

v4 API-তে নাম, স্ট্রাকচার ও বিভিন্ন প্যারামিটারের জন্য সহায়তা পরিবর্তন করা হয়েছে। আমরা সুপারিশ করি যে আপনি ফিল্ড মাস্ক ব্যবহার করুন যাতে আপনি উত্তরে যে ফিল্ডগুলি চান তা নির্দিষ্ট করতে পারেন।

প্যারামিটার পরিবর্তনের অনুরোধ করুন

v3 প্যারামিটার v4 প্যারামিটার নোট
address, components address URL পাথে এখন আনস্ট্রাকচার্ড ঠিকানা (v3 address) পাস করা হয়। স্ট্রাকচার্ড অ্যাড্রেস কম্পোনেন্ট (v3 components) address.* কোয়েরি প্যারামিটার হিসেবে পাস করা যেতে পারে। v3 কম্পোনেন্ট ফিল্টার রিপ্রোডিউস করুন দেখুন।
bounds locationBias.rectangle নাম পরিবর্তন করা হয়েছে; স্ট্রাকচার পরিবর্তন করে অবজেক্ট করা হয়েছে।
language languageCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 Accept-Language হেডার ব্যবহার করে বা ডিফল্ট হিসেবে en ব্যবহার করে, যেখানে v4 ডিফল্ট হিসেবে লোকেশনের স্থানীয় ভাষা ও স্ক্রিপ্ট ব্যবহার করে।
region regionCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 ডিফল্ট হিসেবে us-এ সেট হয়ে যায়, যেখানে v4-এর কোনও ডিফল্ট ভ্যালু নেই।
extra_computations সরানো হয়েছে SearchDestinations পদ্ধতি দ্বারা প্রতিস্থাপিত হয়েছে।

উত্তর যোগ করার ফিল্ডে পরিবর্তন

v3 ফিল্ড v4 ফিল্ড নোট
status, error_message সরানো হয়েছে v4 HTTP স্ট্যাটাস কোড এবং এরর বডি ব্যবহার করে।
results.address_components.long_name / results.address_components.short_name results.addressComponents.longText / results.addressComponents.shortText নাম পরিবর্তন করা হয়েছে।
results.geometry.location_type results.granularity নাম পরিবর্তন করা হয়েছে।
results.geometry.location results.location ফিল্ডের নাম: lat/lng -> latitude/longitude.
results.geometry.viewport results.viewport ফিল্ডের নাম: northeast/southwest -> high/low.
results.postcode_localities results.postalCodeLocalities নাম পরিবর্তন করা হয়েছে। এখন এক বা একাধিক লোকালিটির জন্য ফেরত দেওয়া হয়েছে (v3-এর জন্য >১ প্রয়োজন)।
results.partial_match সরানো হয়েছে
নতুন results.addressComponents.languageCode নির্দিষ্ট ঠিকানা কম্পোনেন্টের ভাষা।
নতুন results.bounds high/low ব্যবহার করে এক্সপ্লিসিট বাউন্ড।
নতুন results.place জায়গার জন্য রিসোর্সের নাম।
নতুন results.postalAddress স্ট্রাকচার্ড PostalAddress অবজেক্ট।

v3 কম্পোনেন্ট ফিল্টার রিপ্রোডিউস করুন

Geocoding v3-এর ফরওয়ার্ড জিওকোডিংয়ে একটি components প্যারামিটার অন্তর্ভুক্ত ছিল যা নির্দিষ্ট কম্পোনেন্টের (যেমন, components=country:US) জন্য ফলাফলের হার্ড ফিল্টারিং চালু করেছিল। v4-এর ফরওয়ার্ড জিওকোডিং, অনুরোধের প্যারামিটারে এই ধরনের হার্ড ফিল্টারিং সমর্থন করে না। v4-এ, আপনি ঠিকানার তথ্য পাথে একটি আনস্ট্রাকচার্ড স্ট্রিং হিসেবে অথবা address.addressLines, address.locality, address.administrativeArea, address.postalCode এবং address.regionCode-এর মতো স্ট্রাকচার্ড কোয়েরি প্যারামিটার হিসেবে দিতে পারেন। স্ট্রাকচার্ড প্যারামিটার হার্ড ফিল্টার হিসেবে কাজ করে না। পরিবর্তে, API যে সম্পূর্ণ ঠিকানা জিওকোড করার চেষ্টা করবে, সেটি তৈরি করতে, প্রদান করা সব কম্পোনেন্ট একত্রিত করা হয়। API সব কম্পোনেন্ট জুড়ে নির্দিষ্ট করা সম্পূর্ণ ঠিকানার জন্য সবচেয়ে উপযুক্ত ম্যাচ সার্চ করে। স্ট্রাকচার্ড উপায়ে কম্পোনেন্ট প্রদান করলে, API-এর পক্ষে উদ্দেশ্য আরও ভালোভাবে বোঝা সম্ভব হয়, বিশেষত যখন আলাদা ফর্ম ফিল্ড থেকে ঠিকানা সংক্রান্ত তথ্য সংগ্রহ করা হয়। এটি API-কে প্রতিটি কম্পোনেন্টের মধ্যে ছোটখাটো টাইপো বা অস্পষ্টতা ম্যানেজ করতে সাহায্য করতে পারে, কারণ প্রতিটি ফিল্ডে তথ্যের ধরন স্পষ্ট।

v3-এর হার্ড কম্পোনেন্ট ফিল্টারের মতো আচরণ পেতে, আপনাকে অবশ্যই v4 API দ্বারা রিটার্ন করা results অ্যারেতে ক্লায়েন্ট-সাইড ফিল্টারিং প্রয়োগ করতে হবে, যা রেসপন্সে postalAddress এবং addressComponents অবজেক্টের উপর ভিত্তি করে।

নিচের সারণীতে v3 components ফিল্টার এবং v4 postalAddress ফিল্ডের মধ্যে সবচেয়ে ভাল মিল দেখানো হয়েছে:

v3 কম্পোনেন্ট ফিল্টার v4 উত্তর যোগ করার ফিল্ড
country postalAddress.regionCode
postal_code postalAddress.postalCode
administrative_area postalAddress.administrativeArea বা addressComponents

ক্লায়েন্ট-সাইড ফিল্টারিংয়ের উদাহরণ

নিম্নলিখিত উদাহরণগুলি দেখায় যে কীভাবে ফলাফলগুলি ফিল্টার করতে হয় যাতে v3 কম্পোনেন্ট ফিল্টারিংয়ের মতো আচরণ অর্জন করা যায়, যা সমর্থিত ফিল্ডগুলির জন্য: দেশ, প্রশাসনিক এলাকা এবং পোস্টাল কোড। অন্যান্য ফিল্ডে ফিল্টার করার সাজেশন দেওয়া হয় না কারণ নির্ভরযোগ্য ফিল্টারিংয়ের মাপকাঠি নেই।

দেশ অনুযায়ী ফিল্টার করুন

আপনার অনুরোধ থেকে address.regionCode-এর সাথে প্রতিটি ফলাফলে postalAddress.regionCode-এর মিল আছে কিনা তা দেখুন। মনে রাখবেন, API অনুরোধে ছোট হাতের অক্ষরে লেখা অঞ্চল কোড গ্রহণ করলেও, এটি সবসময় উত্তরে বড় হাতের অক্ষরে লেখা অঞ্চল কোড দেখায়, তাই তুলনা করার আগে আপনাকে অবশ্যই ইনপুটটি বড় হাতের অক্ষরে পরিবর্তন করতে হবে।

Python কোডের উদাহরণ
def filter_by_country(results, region_code):
    return [
        res for res in results
        if res.get('postalAddress', {}).get('regionCode') == region_code.upper()
    ]

# Example usage:
# v4_response = ... # API call response
# filtered = filter_by_country(v4_response.get('results', []), 'US')
Node.js কোডের উদাহরণ
function filterByCountry(results, regionCode) {
    return results.filter(res => res.postalAddress?.regionCode === regionCode.toUpperCase());
}

// Example usage:
// const v4Response = ... # API call response
// const filtered = filterByCountry(v4Response.results, 'US');
প্রশাসনিক এলাকা অনুযায়ী ফিল্টার করুন

আপনার অনুরোধ থেকে address.administrativeArea-এর সাথে প্রতিটি ফলাফলে postalAddress.administrativeArea-এর মিল আছে কিনা তা দেখুন। দেশীয় কোডের মতো, তুলনা করার আগে আপনার ইনপুট বড় হাতের অক্ষরে নরমালাইজ করা উচিত। আপনার অনুরোধে administrativeArea স্ট্যান্ডার্ড ২-অক্ষরের সংক্ষিপ্ত রূপের সাথে প্রদান করা হলে তবেই এটি নির্ভরযোগ্য। বিভিন্ন কারণে উত্তরে postalAddress.administrativeArea সরাসরি ISO 3166-2 কোড সাফিক্সের সাথে নাও মিলতে পারে। প্রথমত, কিছু এলাকায় ISO 3166-2 কোডের সাথে সম্পর্কিত সাবডিভিশন ডাক ঠিকানার স্ট্যান্ডার্ড উপস্থাপনার অংশ নয়। যেমন, স্পেনে, প্রশাসনিক এলাকা লেভেল ১ (যেমন, ক্যানারিয়াসের জন্য "CN") addressComponents-এ থাকতে পারে, কিন্তু postalAddress.administrativeArea-এ লেভেল ২ এলাকা (যেমন, "Santa Cruz de Tenerife") থাকতে পারে। দ্বিতীয়ত, কিছু অঞ্চলে সাবডিভিশনের সংক্ষিপ্ত রূপ সাধারণত ব্যবহার করা হয় না এবং postalAddress.administrativeArea-এ এটি আরও বড় নামে দেখানো হয় (একই কারণে, সাবডিভিশনের সাথে সম্পর্কিত অ্যাড্রেস কম্পোনেন্টের জন্য addressComponents.shortText সাবডিভিশনের ISO 3166-2 কোড সাফিক্সের সাথে নাও মিলতে পারে)। এছাড়াও, কিছু ক্ষেত্রে সাবডিভিশন, administrative_area_level_n-এর জন্য অ্যাড্রেস কম্পোনেন্টে দেখানো হতে পারে, যেখানে n-এর মান ১-এর বেশি। সবচেয়ে বিস্তারিত ফলাফল পেতে, আপনাকে postalAddress.administrativeArea এবং administrative_area_level_n ধরনের (যেমন, administrative_area_level_1) যেকোনও addressComponents-এর মধ্যে মিল আছে কিনা তা চেক করতে হবে।

Python কোডের উদাহরণ
def filter_by_admin_area(results, admin_area):
    target = admin_area.upper()
    filtered = []
    for res in results:
        # Check postalAddress
        pa_aa = res.get('postalAddress', {}).get('administrativeArea', '')
        if pa_aa == target:
            filtered.append(res)
            continue
        # Check all administrative area levels in addressComponents
        for comp in res.get('addressComponents', []):
            is_admin_level = any(t.startswith('administrative_area_level_')
                               for t in comp.get('types', []))
            if is_admin_level:
                short = comp.get('shortText', '')
                if short == target:
                    filtered.append(res)
                    break
    return filtered

# Example usage:
# filtered = filter_by_admin_area(v4_response.get('results', []), 'CA')
Node.js কোডের উদাহরণ
function filterByAdminArea(results, adminArea) {
    const target = adminArea.toUpperCase();
    return results.filter(res => {
        // Check postalAddress.administrativeArea
        if (res.postalAddress?.administrativeArea === target) {
            return true;
        }
        // Check addressComponents for any administrative area level
        return res.addressComponents?.some(c => {
            const isAdmin = c.types?.some(t => t.startsWith('administrative_area_level_'));
            return isAdmin && c.shortText === target;
        });
    });
}

// Example usage:
// const filtered = filterByAdminArea(v4Response.results, 'CA');
পিন কোড অনুযায়ী ফিল্টার করুন

আপনার অনুরোধ থেকে address.postalCode-এর সাথে প্রতিটি ফলাফলে postalAddress.postalCode-এর মিল আছে কিনা তা দেখুন। তুলনা করার আগে আপনাকে অবশ্যই ইনপুট এবং ফলাফল পোস্টাল কোড দুটিই স্বাভাবিক করতে হবে। নর্মালাইজেশন লজিক অঞ্চলের উপর অত্যন্ত নির্ভরশীল। একটি প্রাথমিক পদ্ধতিতে স্পেস ও হাইফেন সরিয়ে দেওয়া এবং একটি সামঞ্জস্যপূর্ণ কেসে পরিবর্তন করা অন্তর্ভুক্ত।

পোস্টাল কোডের প্রিফিক্স (যেমন, যুক্তরাজ্যে "L2") বা সাফিক্স (যেমন, মার্কিন যুক্তরাষ্ট্রের পিন কোডে "+4") ম্যানেজ করার জন্য আরও উন্নত নরমালাইজেশনের প্রয়োজন হতে পারে। প্রয়োজনীয় নির্দিষ্ট নরমালাইজেশন লজিক দেশ এবং পোস্টাল কোডের ফর্ম্যাটের উপর নির্ভর করে পরিবর্তিত হবে। আপনাকে হয়ত প্রদত্ত নরমালাইজেশন ফাংশন অ্যাডাপ্ট করতে হবে অথবা আপনি যে অঞ্চলকে টার্গেট করছেন তার জন্য আরও জটিল লজিক প্রয়োগ করতে হবে।

প্রদত্ত উদাহরণটি মার্কিন যুক্তরাষ্ট্রের পিন কোড ম্যানেজ করে এবং ZIP+4 প্রদান বা ফেরত দেওয়া হলেও ৫-সংখ্যার বেসে মিল করার অনুমতি দেয়।

Python কোডের উদাহরণ (মার্কিন যুক্তরাষ্ট্রের পিন কোডের উপর ফোকাস করা)
import re

def normalize_postal_code_us(pc):
    # Basic normalization for US: uppercase, alphanumeric only
    if not pc:
        return ""
    normalized = re.sub(r'[^A-Z0-9]', '', pc.upper())
    # Return only the first 5 digits for US ZIP codes
    return normalized[:5]

def filter_by_postal_code_us(results, postal_code):
    normalized_input = normalize_postal_code_us(postal_code)
    if not normalized_input:
        return []
    filtered_results = []
    for res in results:
        pa_pc = res.get('postalAddress', {}).get('postalCode', '')
        if normalize_postal_code_us(pa_pc) == normalized_input:
            filtered_results.append(res)
    return filtered_results

# Example usage:
# Matches '94043', '94043-1351', '940431351'
# filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043')
# filtered = filter_by_postal_code_us(v4_response.get('results', []), '94043-1234')
Node.js কোডের উদাহরণ (মার্কিন যুক্তরাষ্ট্রের পিন কোডের উপর ফোকাস করা)
function normalizePostalCodeUs(pc) {
    // Basic normalization for US: uppercase, alphanumeric only
    const normalized = (pc || '').toUpperCase().replace(/[^A-Z0-9]/g, '');
    // Return only the first 5 digits for US ZIP codes
    return normalized.substring(0, 5);
}

function filterByPostalCodeUs(results, postalCode) {
    const normalizedInput = normalizePostalCodeUs(postalCode);
    if (!normalizedInput) {
        return [];
    }
    return results.filter(res => {
        const paPc = res.postalAddress?.postalCode || '';
        return normalizePostalCodeUs(paPc) === normalizedInput;
    });
}

// Example usage:
// Matches '94043', '94043-1351', '940431351'
// const filtered = filterByPostalCodeUs(v4Response.results, '94043');
// const filtered = filterByPostalCodeUs(v4Response.results, '94043-1234');

v3 রিভার্স জিওকোডিং থেকে মাইগ্রেট করা

আপনি যদি স্থানাঙ্ককে ঠিকানায় পরিবর্তন করতে v3 রিভার্স জিওকোডিং ব্যবহার করেন, তাহলে আপনাকে v4 লোকেশন রিভার্স জিওকোড করুন পদ্ধতিতে মাইগ্রেট করতে হবে, যা GET অনুরোধ গ্রহণ করে।

v4 API-তে নাম, স্ট্রাকচার ও বিভিন্ন প্যারামিটারের জন্য সহায়তা পরিবর্তন করা হয়েছে। আমরা সুপারিশ করি যে আপনি ফিল্ড মাস্ক ব্যবহার করুন যাতে আপনি উত্তরে যে ফিল্ডগুলি চান তা নির্দিষ্ট করতে পারেন।

প্যারামিটার পরিবর্তনের অনুরোধ করুন

v3 প্যারামিটার v4 প্যারামিটার নোট
language languageCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 Accept-Language হেডার ব্যবহার করে বা ডিফল্ট হিসেবে en ব্যবহার করে, যেখানে v4 ডিফল্ট হিসেবে লোকেশনের স্থানীয় ভাষা ও স্ক্রিপ্ট ব্যবহার করে।
region regionCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 ডিফল্ট হিসেবে us-এ সেট হয়ে যায়, যেখানে v4-এর কোনও ডিফল্ট ভ্যালু নেই।
result_type types নাম পরিবর্তন করা হয়েছে; বারবার কোয়েরি প্যারামিটার ব্যবহার করে।
location_type granularity নাম পরিবর্তন করা হয়েছে; বারবার কোয়েরি প্যারামিটার ব্যবহার করে।
extra_computations সরানো হয়েছে SearchDestinations পদ্ধতি দ্বারা প্রতিস্থাপিত হয়েছে।

উত্তর যোগ করার ফিল্ডে পরিবর্তন

v3 ফিল্ড v4 ফিল্ড নোট
status, error_message সরানো হয়েছে v4 HTTP স্ট্যাটাস কোড এবং এরর বডি ব্যবহার করে।
results.address_components.long_name / results.address_components.short_name results.addressComponents.longText / results.addressComponents.shortText নাম পরিবর্তন করা হয়েছে।
results.geometry.location_type results.granularity নাম পরিবর্তন করা হয়েছে।
results.geometry.location results.location ফিল্ডের নাম: lat/lng -> latitude/longitude.
results.geometry.viewport results.viewport ফিল্ডের নাম: northeast/southwest -> high/low।
নতুন results.addressComponents.languageCode নির্দিষ্ট ঠিকানা কম্পোনেন্টের ভাষা।
নতুন results.bounds high/low ব্যবহার করে এক্সপ্লিসিট বাউন্ড।
নতুন results.place জায়গার জন্য রিসোর্সের নাম।
নতুন results.postalAddress স্ট্রাকচার্ড PostalAddress অবজেক্ট।

v3 ঠিকানা বর্ণনাকারী থেকে মাইগ্রেট করুন

Geocoding API v3-তে, extra_computations=ADDRESS_DESCRIPTORS পাস করার ফলে address_descriptor অবজেক্ট রিটার্ন করা হয়েছে, যার মধ্যে landmarks[] ও areas[] আছে। Geocoding API v4-এ, এই ক্ষমতা SearchDestinations পদ্ধতি (POST /v4/geocode/destinations) দ্বারা প্রতিস্থাপিত হয়, যা প্রতিটি Destination অবজেক্টের মধ্যে সরাসরি সমৃদ্ধ স্থানিক প্রসঙ্গ প্রদান করে।

নিম্নলিখিত সারণী পুরনো v3 address_descriptor ফিল্ডকে v4 SearchDestinations সমতুল্য ফিল্ডের সাথে ম্যাপ করে:

v3 address_descriptor ফিল্ড v4 SearchDestinations ফিল্ড মাইগ্রেশন নোট
landmarks[] destinations[].landmarks[] আপনার X-Goog-FieldMask-এ destinations.landmarks-এর জন্য অনুরোধ করুন।
landmarks[].place_id landmarks[].place.placeId place (PlaceView) অবজেক্টের মধ্যে র‍্যাপ করা আছে।
landmarks[].display_name landmarks[].place.displayName স্থানীয়করণ করা টেক্সট (text এবং languageCode)।
landmarks[].types landmarks[].place.types জায়গার ধরন সংক্রান্ত স্ট্রিংয়ের অ্যারে।
landmarks[].spatial_relationship landmarks[].relationalDescription র enum (ACROSS_THE_ROAD, AROUND_THE_CORNER)-এর পরিবর্তে, v4 লোকালাইজ করা, মানুষের-পঠনযোগ্য বাক্যাংশ (যেমন, "Across from Central Park") রিটার্ন করে।
landmarks[].straight_line_distance_meters landmarks[].straightLineDistanceMeters নাম পরিবর্তন করে lower camelCase করা হয়েছে।
landmarks[].travel_distance_meters landmarks[].travelDistanceMeters নাম পরিবর্তন করে lower camelCase করা হয়েছে।
areas[] (containment enum) destinations[].containingPlaces[] ও subDestinations[] স্ট্রাকচারাল হায়ারার্কির জন্য সবচেয়ে কাছাকাছি উপলভ্য সমতুল্য: এনক্লোজিং কমপ্লেক্স, ক্যাম্পাস, মল এবং বিল্ডিং containingPlaces[] এবং subDestinations[]-এ স্ট্রাকচার্ড PlaceView অবজেক্ট হিসেবে রিটার্ন করা হয় (structureType-কে GROUNDS বা BUILDING এবং ঐচ্ছিক displayPolygon আউটলাইন হিসেবে সেট করা হয়)। মনে রাখবেন যে, প্রতিবেশী/জেলা প্রক্সিমিটি এলাকা বা v3 containment enum (NEAR, WITHIN, OUTSKIRTS)-এর জন্য কোনও সরাসরি ১:১ রিপ্লেসমেন্ট নেই।

v3 Place জিওকোডিং থেকে মাইগ্রেট করুন

আপনি যদি Geocoding v3-এর মাধ্যমে কোনও নির্দিষ্ট প্লেস আইডির ঠিকানা পেতে place_id ব্যবহার করেন, তাহলে আপনাকে v4 Place Geocoding পদ্ধতিতে মাইগ্রেট করতে হবে, যা GET অনুরোধ গ্রহণ করে।

v4 API-তে নাম, স্ট্রাকচার ও বিভিন্ন প্যারামিটারের জন্য সহায়তা পরিবর্তন করা হয়েছে। আমরা সুপারিশ করি যে আপনি ফিল্ড মাস্ক ব্যবহার করুন যাতে আপনি উত্তরে যে ফিল্ডগুলি চান তা নির্দিষ্ট করতে পারেন।

প্যারামিটার পরিবর্তনের অনুরোধ করুন

v3 প্যারামিটার v4 প্যারামিটার নোট
place_id অনুরোধ প্রোটোতে place ফিল্ড প্লেস আইডি এখন পাথ প্যারামিটার places/{place} হিসেবে প্রদান করা হয়, যেমন: https://geocode.googleapis.com/v4/geocode/places/ChIJj61dQgK6j4AR4GeTYWZsKWw। এটি অন্তর্নিহিত অনুরোধে জায়গার ফিল্ডে ম্যাপ করে।
language languageCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 Accept-Language হেডার ব্যবহার করে বা ডিফল্ট হিসেবে en ব্যবহার করে, যেখানে v4 ডিফল্ট হিসেবে লোকেশনের স্থানীয় ভাষা ও স্ক্রিপ্ট ব্যবহার করে।
region regionCode নাম পরিবর্তন করা হয়েছে। বাদ দেওয়া হলে, v3 ডিফল্ট হিসেবে us-এ সেট হয়ে যায়, যেখানে v4-এর কোনও ডিফল্ট ভ্যালু নেই।

উত্তর যোগ করার ফিল্ডে পরিবর্তন

v3 ফিল্ড v4 ফিল্ড নোট
status, error_message সরানো হয়েছে v4 HTTP স্ট্যাটাস কোড এবং এরর বডি ব্যবহার করে।
results (root) v4 একটি একক ফলাফল অবজেক্ট রিটার্ন করে, results অ্যারে নয়।
results.address_components.long_name / results.address_components.short_name addressComponents.longText / addressComponents.shortText নাম পরিবর্তন করা হয়েছে।
results.geometry.location_type granularity নাম পরিবর্তন করা হয়েছে।
results.geometry.location location ফিল্ডের নাম: lat/lng -> latitude/longitude.
results.geometry.viewport viewport ফিল্ডের নাম: northeast/southwest -> high/low.
results.postcode_localities postalCodeLocalities নাম পরিবর্তন করা হয়েছে। এখন এক বা একাধিক লোকালিটির জন্য ফেরত দেওয়া হয়েছে (v3-এর জন্য >১ প্রয়োজন)।
নতুন addressComponents.languageCode নির্দিষ্ট ঠিকানা কম্পোনেন্টের ভাষা।
নতুন bounds high/low ব্যবহার করে এক্সপ্লিসিট বাউন্ড।
নতুন place জায়গার জন্য রিসোর্সের নাম।
নতুন postalAddress স্ট্রাকচার্ড PostalAddress অবজেক্ট।

জিওকোডিং হাইপারলোকাল ডেটা থেকে ডেস্টিনেশনে মাইগ্রেট করা

Geocoding API v3-এর নিম্নলিখিত ফিচারগুলি Geocoding API v4-এর SearchDestinations পদ্ধতি দ্বারা পরিবর্তন করা হচ্ছে:

  • প্রবেশপথ
  • নেভিগেশন পয়েন্ট
  • বিল্ডিংয়ের আউটলাইন
  • গ্রাউন্ডগুলি

আপনি যদি উপরের ফিচারগুলির জন্য Geocoding API v3 ব্যবহার করে থাকেন, তাহলে এই ডকুমেন্ট ব্যবহার করুন এই ফিচারগুলি পেতে পরিবর্তে SearchDestinations পদ্ধতি ব্যবহার করতে আপনাকে সাহায্য করতে। এই ডকুমেন্ট থেকে আপনি জানতে পারবেন যে SearchDestinations রেসপন্সের কোথায় এইসব ফিচার খুঁজে পাবেন এবং Geocoding API v3 ও Geocoding API v4-এর SearchDestinations পদ্ধতির মধ্যে API রেসপন্সে এইসব ফিচার কীভাবে দেখানো হয় তার পার্থক্য।

প্রবেশপথ

destination-এর সাথে সম্পর্কিত প্রবেশপথ পেতে, destination.entrances ফিল্ড ব্যবহার করুন।

destination.entrances-এ প্রতিটি entrance-এ নিম্নলিখিত ফিল্ড আছে (পুরনো v3 buildings.entrances স্কিমা পরিবর্তন করে):

  • displayName - একটি নতুন ঐচ্ছিক ফিল্ড যাতে প্রবেশপথের জন্য মানুষের-পঠনযোগ্য নাম থাকে, যেমন "Gate B"।
  • location - latitude ও longitude ব্যবহার করে LatLng ধরনের লোকেশন (v3 lat/lng-এর পরিবর্তে)।
  • tags - Geocoding API v3 প্রবেশপথের (যেমন PREFERRED) tags ফিল্ডের মতো একই।
  • place - জায়গার রিসোর্স নাম (যেমন, places/ChIJ...), Geocoding API v3 থেকে building_place_id ফিল্ডটি পরিবর্তন করা হচ্ছে। v4-এ, এই জায়গাটি শুধু বিল্ডিং নয়, যেকোনও গন্তব্য স্ট্রাকচার (বিল্ডিং, ক্যাম্পাস বা পার্ক) দেখাতে পারে।

destination-এর সাথে যুক্ত নেভিগেশন পয়েন্ট পেতে, destination.navigationPoints ফিল্ড ব্যবহার করুন।

destination.navigationPoints-এ প্রতিটি navigationPoint-এ নিম্নলিখিত ফিল্ড আছে (পুরনো v3 navigation_points স্কিমা পরিবর্তন করে):

  • navigationPointToken - Routes API ComputeRoutes পদ্ধতিতে (Waypoint.navigationPointToken) এই নির্দিষ্ট নেভিগেশন পয়েন্টে রুট করার জন্য ব্যবহৃত একটি এনক্রিপ্ট করা টোকেন স্ট্রিং। নেভিগেশন পয়েন্ট টোকেন ব্যবহার করে রুট দেখুন।
  • displayName - একটি নতুন ঐচ্ছিক ফিল্ড যাতে নেভিগেশন পয়েন্টের জন্য মানুষের-পঠনযোগ্য নাম থাকে, যেমন "5th Ave"।
  • location - latitude এবং longitude ব্যবহার করে LatLng ধরনের লোকেশন।
  • travelModes - Geocoding API v3-এর restricted_travel_modes ফিল্ডের মতো, তবে v4-এ সীমাবদ্ধ ট্রাভেল মোডের পরিবর্তে গ্রহণযোগ্য ট্রাভেল মোড (DRIVE, WALK) উল্লেখ করা হয়।
  • usage - নেভিগেশন পয়েন্টের জন্য (যেমন PICKUP, DROPOFF বা PARKING) কাজ করে এমন আগমন সংক্রান্ত ব্যবহারের কেস উল্লেখ করে একটি নতুন ফিল্ড।

বিল্ডিংয়ের আউটলাইন

destination-এর সাথে সম্পর্কিত বিল্ডিংয়ের আউটলাইন পেতে, destination-এর মধ্যে placeView অবজেক্টের displayPolygon ফিল্ড ব্যবহার করুন যা বিল্ডিংকে দেখায় (পুরনো v3 buildings.building_outlines অ্যারে রিপ্লেস করে)। প্রতিটি placeView-এর জন্য, এটি placeView.structureType ফিল্ড সহ কোনও বিল্ডিং কিনা তা চেক করুন। স্ট্রাকচারের ধরন BUILDING হলে, আপনি placeView.displayPolygon ফিল্ড থেকে আউটলাইন পেতে পারেন। এছাড়াও, placeView-এ বিল্ডিংয়ের জন্য অতিরিক্ত ফিল্ড থাকবে যা Geocoding API v3-তে ছিল না।

destination-এ placeView অবজেক্ট থাকতে পারে যা নিম্নলিখিত ফিল্ডে বিল্ডিংকে দেখায়:

  • destination.primary - গন্তব্যের প্রাথমিক জায়গা।
  • destination.containingPlaces - একটি পুনরাবৃত্ত ফিল্ড যা প্রাথমিক স্থান "ধারণ" করে এমন বড় স্থানগুলি ধরে রাখে। যেমন, প্রাথমিক জায়গাটি subpremise হলে, containingPlaces সাধারণত placeView ধারণ করে যা বিল্ডিংকে উপস্থাপন করে।
  • destination.subDestinations - একটি পুনরাবৃত্ত ফিল্ড যা প্রাথমিক জায়গার সাব-ডেস্টিনেশন (যেমন, কোনও বিল্ডিংয়ের মধ্যে স্বতন্ত্র অ্যাপার্টমেন্ট ইউনিট বা স্যুইট) হোল্ড করে।

মনে রাখবেন যে placeView.displayPolygon-এর ফর্ম্যাট Geocoding API v3-এ বিল্ডিং আউটলাইন ফর্ম্যাট-এর সাথে মেলে, যা হল GeoJSON ফর্ম্যাট, RFC 7946 ফর্ম্যাট ব্যবহার করে।

গ্রাউন্ডগুলি

বিল্ডিংয়ের আউটলাইনের মতোই, destination-এর সাথে যুক্ত গ্রাউন্ড পেতে, destination-এর মধ্যে placeView অবজেক্টের displayPolygon ফিল্ড ব্যবহার করুন যা গ্রাউন্ডকে দেখায় (পুরনো v3 grounds অ্যারে প্রতিস্থাপন করে)। প্রতিটি placeView-এর জন্য, এটি placeView.structureType ফিল্ড সহ গ্রাউন্ড পলিগন কিনা তা চেক করুন। যদি স্ট্রাকচারের ধরন GROUNDS হয়, তাহলে আপনি placeView.displayPolygon ফিল্ড থেকে আউটলাইন পেতে পারেন। এছাড়াও, placeView-এ গ্রাউন্ডের জন্য অতিরিক্ত ফিল্ড থাকবে যা Geocoding API v3-তে ছিল না।

destination-এ placeView অবজেক্ট থাকতে পারে যা নিম্নলিখিত ফিল্ডে গ্রাউন্ড দেখায়:

  • destination.primary
  • destination.containingPlaces
  • destination.subDestinations

মনে রাখবেন যে placeView.displayPolygon-এর ফর্ম্যাট Geocoding API v3-তে গ্রাউন্ডস আউটলাইন ফর্ম্যাটের সাথে মেলে, যা RFC 7946 ফর্ম্যাট ব্যবহার করে GeoJSON ফর্ম্যাট।

ফলাফলের নির্ভুলতা

Geocoding API v3-তে, রেসপন্স জিওমেট্রিতে location_type ফিল্ড ফলাফলের নির্ভুলতা নির্দেশ করে এবং কিছু ক্লায়েন্ট এইসব ভ্যালুর (ROOFTOP, RANGE_INTERPOLATED, GEOMETRIC_CENTER এবং APPROXIMATE) উপর ভিত্তি করে ফলাফল র‍্যাঙ্ক বা ফিল্টার করে। স্ট্যান্ডার্ড Geocoding API v4 মাইগ্রেশনে, এই ফিল্ডের নাম পরিবর্তন করে granularity করা হয়েছে।

Destinations API (v4 SearchDestinations)-তে কোনও location_type ফিল্ড নেই। পরিবর্তে, স্থানিক তথ্য আলাদাভাবে ম্যানেজ করা হয়:

  • ম্যানুয়ালি ক্লায়েন্ট-সাইড ফিল্টার করার প্রয়োজন নেই: স্ট্যান্ডার্ড জিওকোডিং বিভিন্ন গ্র্যানুলারিটি জুড়ে একাধিক ফলাফল প্রদান করলেও, SearchDestinations পদ্ধতিটি যখনই সম্ভব একটি একক, অপ্টিমাইজ করা গন্তব্যে সমাধান করে অস্পষ্টতা কমিয়ে দেয়। এর ফলে, কোন ফলাফলটি সবচেয়ে ভালো তা নির্ধারণ করার জন্য ক্লায়েন্টদের লোকেশনের ধরন অনুযায়ী ফিল্টার করার প্রয়োজন হয় না।
  • স্ট্রাকচারের ধরন ও ডিসপ্লে পলিগনের মাধ্যমে দেখানো স্পেশিয়াল তথ্য: স্পেশিয়াল জিওমেট্রি ও স্ট্রাকচার এগুলির মাধ্যমে দেখানো হয়:
    • displayPolygon (সঠিক জ্যামিতির জন্য)।
    • placeView অবজেক্টের মধ্যে structureType ফিল্ড।
  • স্ট্রাকচারের ধরন ম্যাপিং:
    • POINT, BUILDING বা SECTION-এর structureType সাধারণত আগে যাকে ROOFTOP বলা হত তার সাথে মিলে যায়।
    • GROUNDS-এর structureType সাধারণত GEOMETRIC_CENTER-এর সাথে সম্পর্কিত।

এইসব ফিচারের জন্য অনুরোধ করতে ফিল্ড মাস্ক ব্যবহার করুন

SearchDestinations পদ্ধতির জন্য ফিল্ড মাস্ক প্রয়োজন, যেমন ফেরত পাওয়ার জন্য ফিল্ড বেছে নিন বিকল্পে ব্যাখ্যা করা হয়েছে। সব ফিল্ড ফেরত পেতে ফিল্ড মাস্ক *-এ সেট করা যেতে পারে অথবা আপনি যে নির্দিষ্ট ফিল্ড পেতে চান সেটিতে সেট করতে পারেন। যেমন, নিম্নলিখিত API অনুরোধটি কোনও গন্তব্যের প্রবেশপথ, নেভিগেশন পয়েন্ট, বিল্ডিংয়ের আউটলাইন এবং গ্রাউন্ড পাওয়ার জন্য প্রয়োজনীয় সমস্ত ফিল্ড পেতে ফিল্ড মাস্ক সেট করে:

curl -X POST -d '{"place": "places/ChIJG3kh4hq6j4AR_XuFQnV0_t8"}' \
  -H "X-Goog-Api-Key: API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Goog-FieldMask: destinations.entrances,destinations.navigationPoints,destinations.primary,destinations.containingPlaces,destinations.subDestinations" \
  https://geocode.googleapis.com/v4/geocode/destinations

সাধারণ মাইগ্রেশন রেসিপি ও কোড প্যাটার্ন

Geocoding v3 বা Geocoding++ থেকে SearchDestinations-এ জটিল ওয়ার্কফ্লো মাইগ্রেট করার সময়, সাধারণ স্পেশিয়াল ও অ্যাড্রেস স্ট্রাকচার এক্সট্র্যাক্ট করতে নিম্নলিখিত কোড রেসিপি ব্যবহার করুন।

বিল্ডিংয়ের সেরা পলিগন বের করুন

আপনি যদি কোনও লোকেশন বা গন্তব্যের জন্য বিল্ডিং ফুটপ্রিন্ট রেন্ডার করতে চান:

  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 enum (WITHIN, BESIDE, BEHIND, NEAR, ACROSS_THE_ROAD, AROUND_THE_CORNER) ফিরিয়ে দিয়েছে। SearchDestinations-এ:

  • কোনও র-রিলেশনশিপ enum নেই। পরিবর্তে, সরাসরি 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') সহ প্রথম প্রার্থী সর্বোত্তম গাড়ির ওয়েপয়েন্ট প্রদান করে। Routes API ComputeRoutes পদ্ধতিতে (Waypoint.navigationPointToken) বা Navigation SDK-তে এর navigationPointToken পাঠান। রাস্তার সাথে স্ন্যাপ করা কোনও ড্রাইভিং পয়েন্ট না থাকলে, বিল্ডিংয়ের প্রবেশপথ বা প্রাথমিক সেন্ট্রয়েডে ফিরে যান।
  • ফিজিক্যাল ডোরওয়ে অ্যাক্সেস: destinations.entrances ব্যবহার করে বিল্ডিংয়ের প্রবেশপথে হেঁটে যাওয়া কুরিয়ার বা যাত্রীকে গাইড করুন। 'PREFERRED'-এর জন্য tags চেক করে এমন প্রবেশপথ খুঁজুন যা সম্ভবত সরাসরি ফিজিক্যাল অ্যাক্সেস প্রদান করে। প্রবেশপথের কোনও ডেটা উপলভ্য না থাকলে, পথচারী নেভিগেশন পয়েন্ট (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-কে সার্ভার-টু-সার্ভার API হিসেবে ডিজাইন করা হয়েছে। জাভাস্ক্রিপ্ট ব্যবহারকারীদের জন্য v3 থেকে v4-এ মাইগ্রেট করার কোনও সরাসরি উপায় নেই। API কী ব্যবহার করে ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্ট (যেমন, ব্রাউজারে) থেকে সরাসরি v4 মেথড কল করলে, আপনার API কী চুরি ও অপব্যবহার হওয়ার ঝুঁকি অনেক বেড়ে যায়।

HTTP রেফারার সংক্রান্ত বিধিনিষেধ, কার্যকর হলেও, ওয়েব পরিষেবা এন্ডপয়েন্টের জন্য পর্যাপ্ত সুরক্ষা নয় কারণ আক্রমণকারীরা তাদের অনুরোধে Referer হেডার জাল করে সহজেই এটি বাইপাস করতে পারে।

Geocoding API v4 ব্যবহার করার জন্য আপনার নিজস্ব ব্যাকএন্ড সার্ভার ব্যবহার করার সাজেশন দেওয়া হয়। আপনার ক্লায়েন্ট অ্যাপ্লিকেশনকে এই মধ্যবর্তী সার্ভারে অনুরোধ করতে হবে, যা তারপর সুরক্ষিত API কী (যেমন, এনভায়রনমেন্ট ভেরিয়েবল বা সিক্রেট ম্যানেজারে স্টোর করা কী) ব্যবহার করে Google API-কে নিরাপদে কল করে। এটি নিশ্চিত করে যে আপনার API কী ফ্রন্টএন্ড কোডে কখনও প্রকাশ করা হবে না।

ক্লায়েন্ট-সাইডের প্রয়োজনীয়তার বিকল্প

আপনার যদি ক্লায়েন্ট-সাইড সংক্রান্ত এমন কোনও প্রয়োজন থাকে যার জন্য জিওকোডিং প্রয়োজন, তাহলে আগে থেকে উপলভ্য ক্লায়েন্ট-সাইড সমাধানগুলির মধ্যে কোনও একটি ব্যবহার করার কথা বিবেচনা করুন: