Text Search (新版)

歐洲經濟區 (EEA) 開發人員

Text Search (新版) 會接收文字查詢,然後傳回相���地點清單。

Text Search (新版) 可根據字串 (例如「台南魯肉飯」、「西門町附近的鞋店」或「中正路 123 號」),傳回一組地點的相關資訊。這項服務會傳回與文字字串及位置自訂調整設定相符的地點清單。您可以運用 Text Search (新版) 按照類型搜尋地點、使用營業時間和評分等條件進行篩選,以及將結果的範圍限制或自訂調整為特定地點。

如要使用 Text Search (新版),請務必在 Google Cloud 專案中啟用「Places API (新版)」。詳情請參閱「開始使用」一文。

透過文字查詢尋找多個地點

呼叫 searchByText 即可根據文字查詢或電話號碼傳回地點清單。 請使用要求來指定搜尋參數,然後呼叫 searchByText()。系統會以 Place 物件清單的形式傳回結果,您可從中取得地點詳細資料。以下程式碼片段範例顯示一項要求,以及對 searchByText 的呼叫:

TypeScript

const request = {
    textQuery: query,
    fields: ['displayName', 'location', 'businessStatus'],
    includedType: '', // Restrict query to a specific type (leave blank for any).
    useStrictTypeFiltering: true,
    locationBias: map.center,
    isOpenNow: true,
    language: 'en-US',
    maxResultCount: 8,
    minRating: 1, // Specify a minimum rating.
    region: 'us',
};

const { places } = await Place.searchByText(request);

JavaScript

const request = {
    textQuery: query,
    fields: ['displayName', 'location', 'businessStatus'],
    includedType: '', // Restrict query to a specific type (leave blank for any).
    useStrictTypeFiltering: true,
    locationBias: map.center,
    isOpenNow: true,
    language: 'en-US',
    maxResultCount: 8,
    minRating: 1, // Specify a minimum rating.
    region: 'us',
};
const { places } = await Place.searchByText(request);
  • 使用 textQuery 參數指定要搜尋的文字查詢或電話號碼。
  • fields 參數 (必要) 可指定一份以半形逗號分隔的清單,其中包含一或多個採用駝峰式大小寫的資料欄位
  • 使用 includedType 參數,只傳回指定類型的結果。
  • 使用 locationBiaslocationRestriction,可將文字搜尋結果的範圍限制或自訂調整為特定區域。
查看完整的屬性清單。

如果查詢內含電話號碼,則應設定 region 參數。舉例來說,如果您使用電話號碼搜尋日本的地點,且要求網域為 jp,就必須將 region 參數設為「jp」。如果在要求中省略 region,API 會預設為美國 (「us」) 區域。

系統會以 Place 物件清單的形式傳回結果,您可從中取得地點詳細資料

範例

下例會使用提供的查詢文字呼叫 searchByText,然後在地圖中填入可點選的標記,以顯示查詢結果。

TypeScript

let map;
let markers = {};
let infoWindow;

async function initMap() {
    const { Map, InfoWindow } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

    const center = { lat: 37.4161493, lng: -122.0812166 };
    map = new Map(document.getElementById('map') as HTMLElement, {
        center: center,
        zoom: 11,
        mapTypeControl: false,
        mapId: 'DEMO_MAP_ID',
    });

    const textInput = document.getElementById('text-input') as HTMLInputElement;
    const textInputButton = document.getElementById('text-input-button') as HTMLButtonElement;
    const card = document.getElementById('text-input-card') as HTMLElement;
    map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);

    textInputButton.addEventListener('click', () => {
        findPlaces(textInput.value);
    });

    textInput.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
            findPlaces(textInput.value);
        }
    });

    infoWindow = new google.maps.InfoWindow();
}

async function findPlaces(query) {
    const { Place } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
    const request = {
        textQuery: query,
        fields: ['displayName', 'location', 'businessStatus'],
        includedType: '', // Restrict query to a specific type (leave blank for any).
        useStrictTypeFiltering: true,
        locationBias: map.center,
        isOpenNow: true,
        language: 'en-US',
        maxResultCount: 8,
        minRating: 1, // Specify a minimum rating.
        region: 'us',
    };

    const { places } = await Place.searchByText(request);

    if (places.length) {
        const { LatLngBounds } = await google.maps.importLibrary("core") as google.maps.CoreLibrary;
        const bounds = new LatLngBounds();

        // First remove all existing markers.
        for (const id in markers) {
            markers[id].map = null;
        };
        markers = {};

        // Loop through and get all the results.
        places.forEach(place => {
            const marker = new AdvancedMarkerElement({
                map,
                position: place.location,
                title: place.displayName,
            });
            markers[place.id] = marker;

            marker.addListener('gmp-click', () => {
                map.panTo(place.location);
                updateInfoWindow(place.displayName, place.id, marker);
            });

            if (place.location != null) {
                bounds.extend(place.location);
            }
        });

        map.fitBounds(bounds);

    } else {
        console.log('No results');
    }
}

// Helper function to create an info window.
async function updateInfoWindow(title, content, anchor) {
    infoWindow.setContent(content);
    infoWindow.setHeaderContent(title);
    infoWindow.open({
        map,
        anchor,
        shouldFocus: false,
    });
}

initMap();

JavaScript

let map;
let markers = {};
let infoWindow;
async function initMap() {
    const { Map, InfoWindow } = await google.maps.importLibrary("maps");
    const center = { lat: 37.4161493, lng: -122.0812166 };
    map = new Map(document.getElementById('map'), {
        center: center,
        zoom: 11,
        mapTypeControl: false,
        mapId: 'DEMO_MAP_ID',
    });
    const textInput = document.getElementById('text-input');
    const textInputButton = document.getElementById('text-input-button');
    const card = document.getElementById('text-input-card');
    map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
    textInputButton.addEventListener('click', () => {
        findPlaces(textInput.value);
    });
    textInput.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
            findPlaces(textInput.value);
        }
    });
    infoWindow = new google.maps.InfoWindow();
}
async function findPlaces(query) {
    const { Place } = await google.maps.importLibrary("places");
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
    const request = {
        textQuery: query,
        fields: ['displayName', 'location', 'businessStatus'],
        includedType: '', // Restrict query to a specific type (leave blank for any).
        useStrictTypeFiltering: true,
        locationBias: map.center,
        isOpenNow: true,
        language: 'en-US',
        maxResultCount: 8,
        minRating: 1, // Specify a minimum rating.
        region: 'us',
    };
    const { places } = await Place.searchByText(request);
    if (places.length) {
        const { LatLngBounds } = await google.maps.importLibrary("core");
        const bounds = new LatLngBounds();
        // First remove all existing markers.
        for (const id in markers) {
            markers[id].map = null;
        }
        ;
        markers = {};
        // Loop through and get all the results.
        places.forEach(place => {
            const marker = new AdvancedMarkerElement({
                map,
                position: place.location,
                title: place.displayName,
            });
            markers[place.id] = marker;
            marker.addListener('gmp-click', () => {
                map.panTo(place.location);
                updateInfoWindow(place.displayName, place.id, marker);
            });
            if (place.location != null) {
                bounds.extend(place.location);
            }
        });
        map.fitBounds(bounds);
    }
    else {
        console.log('No results');
    }
}
// Helper function to create an info window.
async function updateInfoWindow(title, content, anchor) {
    infoWindow.setContent(content);
    infoWindow.setHeaderContent(title);
    infoWindow.open({
        map,
        anchor,
        shouldFocus: false,
    });
}
initMap();

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;
}

#text-input-card {
  width: 25%;
  background-color: #fff;
  border-radius: 5px;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
  margin: 10px;
  padding: 5px;
  font-family: Roboto, sans-serif;
  font-size: large;
  font-weight: bold;
}

#text-input {
  width: 100%;
  padding: 10px;
  margin: 0;
  box-sizing: border-box;
}

#text-input-button {
  display: inline-block;
  margin-top: .5rem;
  width: auto;
  padding: .6rem .75rem;
  font-size: .875rem;
  font-weight: 500;
  color: #fff;
  background-color: #2563eb;
  border: none;
  border-radius: .375rem;
  cursor: pointer;
  transition: background-color .15s ease-in-out;
  text-align: center
}

HTML

<html>
  <head>
    <title>Text Search</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="text-input-card">
      <input type="text" id="text-input" placeholder="Search for a place"></input>
      <input type="button" id="text-input-button" value="Search"></input>
    </div>
    <div id="map"></div>

    <!-- 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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
  </body>
</html>

試用範例