API של נתוני השלמה אוטומטית למקומות

Place השלמה אוטומטית Data API מאפשר לך לאחזר חיזויים לגבי מקומות באופן פרוגרמטי, כדי ליצור חוויה מותאמת אישית של השלמה אוטומטית עם שליטה מדויקת יותר שאפשר לבצע באמצעות הווידג'ט של ההשלמה האוטומטית. במדריך הזה תלמדו איך להשתמש Place השלמה אוטומטית Data API כדי לשלוח בקשות להשלמה אוטומטית על סמך משתמש שאילתות.

הדוגמה הבאה מציגה שילוב פשוט של הקלדה מראש. מזינים את שאילתת החיפוש ולוחצים על כדי לבחור את התוצאה הרצויה.

בקשות להשלמה אוטומטית

בקשה להשלמה אוטומטית מקבלת מחרוזת קלט של שאילתה ומחזירה רשימה של חיזויים לגבי מקומות. שפת תרגום שליחת בקשה להשלמה אוטומטית, התקשרות אל fetchAutocompleteSuggestions() ומעבירים בקשה עם המאפיינים הנדרשים. input הנכס מכיל את המחרוזת לחיפוש; באפליקציה אופיינית, הערך הזה יעודכן כך שהמשתמש מקליד שאילתה. הבקשה צריכה לכלול sessionToken, שמשמש למטרות חיוב.

בקטע הקוד הבא מוצג יצירה של גוף בקשה, הוספת אסימון סשן ואז קריאה לפעולה fetchAutocompleteSuggestions() כדי לקבל רשימה של PlacePrediction.

// Add an initial request body.
let request = {
  input: "Tadi",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};
// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

הגבלת חיזויים של השלמה אוטומטית

כברירת מחדל, ההשלמה האוטומטית של המקום מציגה את כל סוגי המקומות, תוך התייחסות לחיזויים שנמצאים בקרבת המיקום של המשתמש מיקום, ומאחזר את כל שדות הנתונים הזמינים עבור המקום שנבחר על ידי המשתמש. הגדרת מקום אפשרויות להשלמה אוטומטית להצגת חיזויים רלוונטיים יותר על ידי הגבלה או הטייה של התוצאות.

הגבלת התוצאות גורמת לווידג'ט של ההשלמה האוטומטית להתעלם מכל התוצאות שאינן המוגבלות של המשאבים. אחת מהשיטות הנפוצות היא להגביל תוצאות לגבולות המפה. הטיית תוצאות גורם לווידג'ט ההשלמה האוטומטית להציג תוצאות בתוך האזור שצוין, אבל ייתכן שחלק מההתאמות מחוץ לאזור הזה.

משתמשים במאפיין origin כדי לציין את נקודת המוצא שממנה יתבצע החישוב מרחק גיאודזי אל היעד. אם לא מזינים את הערך הזה, לא מוחזר המרחק.

שימוש בincludedPrimaryTypes כדי לציין עד חמישה סוגי מקומות. אם לא תציינו סוגים, יוחזרו מקומות מכל הסוגים.

לעיון בהפניית ה-API

קבלת פרטים על מקום

כדי להחזיר Place מתוצאה של חיזוי מקום, קריאה ראשונה toPlace(), ואז קריאה ל-fetchFields() באובייקט Place שנוצר (מזהה הסשן מחיזוי המקום נכלל באופן אוטומטי). שיחה אל fetchFields() גורמת לסיום של של ההשלמה האוטומטית.

let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});

const placeInfo = document.getElementById("prediction");

placeInfo.textContent =
  "First predicted place: " +
  place.displayName +
  ": " +
  place.formattedAddress;

אסימוני סשן

אסימוני סשן מקבצים את שלבי השאילתה והבחירה של חיפוש ההשלמה האוטומטית של המשתמש סשן נפרד למטרות חיוב. הסשן מתחיל כשהמשתמש מתחיל להקליד. הסשן מסתיים כשהמשתמש בוחר מקום ומבצעת קריאה לפרטי המקום.

כדי ליצור אסימון סשן חדש ולהוסיף אותו לבקשה, צריך ליצור מופע של AutocompleteSessionToken לאחר מכן מגדירים את sessionToken של הבקשה להשתמש באסימונים כפי שמוצג בקטע הקוד הבא:

// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

סשן מסתיים כאשר fetchFields() נקראת. אחרי יצירת המכונה של Place, אין צורך לעבור את הסשן אל fetchFields() כי הוא מטופל באופן אוטומטי.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});
await place.fetchFields({
    fields: ['displayName'],
  });

כדי ליצור אסימון סשן לסשן הבא, יוצרים מופע חדש של AutocompleteSessionToken.

המלצות לאסימוני סשן:

  • שימוש באסימוני הפעלה בכל הקריאות להשלמה אוטומטית של מקומות.
  • ליצור אסימון חדש לכל סשן.
  • מעבירים אסימון סשן ייחודי לכל סשן חדש. שימוש באותו אסימון למשך יותר מסשן אחד יובילו לחיוב של כל בקשה בנפרד.

אם תרצו, תוכלו להשמיט מבקשה את אסימון הסשן של ההשלמה האוטומטית. אם אסימון הסשן הוא שהושמט, כל בקשה מחויבת בנפרד, וכך כתוצאה מכך השלמה אוטומטית – לכל בקשה מק"ט. אם משתמשים שוב באסימון סשן, הסשן נחשב ללא תקין והבקשות יחויבו כאילו לא סופק אסימון סשן.

דוגמה

כשהמשתמש מקליד שאילתה, נשלחת בקשה של השלמה אוטומטית כל כמה (לא לכל תו), ותוחזר רשימה של תוצאות אפשריות. כשהמשתמש יבחר בחירה מתוך רשימת התוצאות, הבחירה נספרת כ: בקשה מסוימת, וכל הבקשות שבוצעו במהלך החיפוש מקובצות יחד נספרת כבקשה אחת. אם המשתמש בוחר מקום, שאילתת החיפוש תהיה זמינים ללא תשלום, ורק הבקשה לנתוני מקום מחויבת. אם המשתמש לא מבצע את הבחירה הזו בתוך מספר דקות מתחילת הפעילות באתר, רק נחייב את שאילתת החיפוש.

מנקודת מבט של אפליקציה, זרימת האירועים מתנהלת כך:

  1. משתמש מתחיל להקליד שאילתה כדי לחפש "פריז, צרפת".
  2. לאחר זיהוי הקלט של המשתמשים, האפליקציה יוצרת סשן חדש ב-'Token A'.
  3. בזמן שהמשתמש מקליד, ה-API שולח בקשה של השלמה אוטומטית כל כמה תווים, ותוצג רשימה חדשה של תוצאות פוטנציאליות לכל:
    'P'
    "Par"
    "Paris,"
    "פריז, פר"
  4. כשהמשתמש בוחר באחת מהאפשרויות הבאות:
    • כל הבקשות שנוצרות מהשאילתה מקובצות ומתווספות סשן שמיוצג על ידי "אסימון א", כבקשה יחידה.
    • הבחירה של המשתמש נספרת כבקשה להצגת פרטי מקום, והיא נוספת לסשן שמיוצג על ידי אסימון א'.
  5. הסשן הסתיים והאפליקציה מוחקת את 'אסימון א'.
מידע נוסף על אופן החיוב של סשנים

השלמת הקוד לדוגמה

קטע זה מכיל דוגמאות מלאות המראות כיצד להשתמש בממשק ה-API של הנתונים להשלמה אוטומטית של Place .

הצבת חיזויים להשלמה אוטומטית

הדוגמה הבאה ממחישה איך להתקשר fetchAutocompleteSuggestions() לקלט 'Tadi', ואז קריאה toPlace() בתוצאת החיזוי הראשונה, ואחריה קריאה אל fetchFields() כדי לקבל פרטים על המקום.

TypeScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
    // @ts-ignore
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: "Tadi",
        locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ["restaurant"],
        language: "en-US",
        region: "us",
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');
        const resultsElement = document.getElementById("results") as HTMLElement;
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById("prediction") as HTMLElement;
    placeInfo.textContent = 'First predicted place: ' + place.displayName + ': ' + place.formattedAddress;

}

init();

JavaScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
  // @ts-ignore
  const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
    await google.maps.importLibrary("places");
  // Add an initial request body.
  let request = {
    input: "Tadi",
    locationRestriction: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
  };
  // Create a session token.
  const token = new AutocompleteSessionToken();

  // Add the token to the request.
  // @ts-ignore
  request.sessionToken = token;

  // Fetch autocomplete suggestions.
  const { suggestions } =
    await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
  const title = document.getElementById("title");

  title.appendChild(
    document.createTextNode('Query predictions for "' + request.input + '":'),
  );

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a new list element.
    const listItem = document.createElement("li");
    const resultsElement = document.getElementById("results");

    listItem.appendChild(
      document.createTextNode(placePrediction.text.toString()),
    );
    resultsElement.appendChild(listItem);
  }

  let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  const placeInfo = document.getElementById("prediction");

  placeInfo.textContent =
    "First predicted place: " +
    place.displayName +
    ": " +
    place.formattedAddress;
}

init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Predictions</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="title"></div>
    <ul id="results"></ul>
    <p><span id="prediction"></span></p>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>

כדאי לנסות דוגמה

שימוש בהקלדה אוטומטית של ההשלמה האוטומטית בסשנים

הדוגמה הזו ממחישה איך להתקשר fetchAutocompleteSuggestions() על סמך שאילתות של משתמשים, הצגת רשימה של מקומות חזויים בתגובה ולבסוף אחזור פרטי המקום לגבי המקום שנבחר. הדוגמה ממחישה גם את השימוש באסימוני סשן כדי: לקבץ שאילתת משתמש עם הבקשה הסופית של פרטי המקום.

TypeScript

let title;
let results;
let input;
let token;

// Add an initial request body.
let request = {
    input: "",
    locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
};

async function init() {
    token = new google.maps.places.AutocompleteSessionToken();

    title = document.getElementById('title');
    results = document.getElementById('results');
    input = document.querySelector("input");
    input.addEventListener("input", makeAcRequest);
    request = refreshToken(request) as any;
}

async function makeAcRequest(input) {
    // Reset elements and exit if an empty string is received.
    if (input.target.value == '') {
        title.innerText = '';
        results.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = input.target.value;

    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    title.innerText = 'Query predictions for "' + request.input + '"';

    // Clear the list first.
    results.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        a.innerText = placePrediction.text.toString();

        // Create a new list element.
        const li = document.createElement('li');
        li.appendChild(a);
        results.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    let placeText = document.createTextNode(place.displayName + ': ' + place.formattedAddress);
    results.replaceChildren(placeText);
    title.innerText = 'Selected Place:';
    input.value = '';
    refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
    // Create a new session token and add it to the request.
    token = new google.maps.places.AutocompleteSessionToken();
    request.sessionToken = token;
    return request;
}

declare global {
    interface Window {
      init: () => void;
    }
  }
  window.init = init;

JavaScript

let title;
let results;
let input;
let token;
// Add an initial request body.
let request = {
  input: "",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};

async function init() {
  token = new google.maps.places.AutocompleteSessionToken();
  title = document.getElementById("title");
  results = document.getElementById("results");
  input = document.querySelector("input");
  input.addEventListener("input", makeAcRequest);
  request = refreshToken(request);
}

async function makeAcRequest(input) {
  // Reset elements and exit if an empty string is received.
  if (input.target.value == "") {
    title.innerText = "";
    results.replaceChildren();
    return;
  }

  // Add the latest char sequence to the request.
  request.input = input.target.value;

  // Fetch autocomplete suggestions and show them in a list.
  // @ts-ignore
  const { suggestions } =
    await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(
      request,
    );

  title.innerText = 'Query predictions for "' + request.input + '"';
  // Clear the list first.
  results.replaceChildren();

  for (const suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a link for the place, add an event handler to fetch the place.
    const a = document.createElement("a");

    a.addEventListener("click", () => {
      onPlaceSelected(placePrediction.toPlace());
    });
    a.innerText = placePrediction.text.toString();

    // Create a new list element.
    const li = document.createElement("li");

    li.appendChild(a);
    results.appendChild(li);
  }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  let placeText = document.createTextNode(
    place.displayName + ": " + place.formattedAddress,
  );

  results.replaceChildren(placeText);
  title.innerText = "Selected Place:";
  input.value = "";
  refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
  // Create a new session token and add it to the request.
  token = new google.maps.places.AutocompleteSessionToken();
  request.sessionToken = token;
  return request;
}

window.init = init;

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

a {
  cursor: pointer;
  text-decoration: underline;
  color: blue;
}

input {
  width: 300px;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Session</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <input id="input" type="text" placeholder="Search for a place..." />
    <div id="title"></div>
    <ul id="results"></ul>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=init&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

כדאי לנסות דוגמה