Text Search (New)

Plattform auswählen: Android iOS JavaScript Webdienst
Entwickler im Europäischen Wirtschaftsraum (EWR)

Bei „Text Search (New)“ wird eine Textabfrage verwendet und eine Liste mit passenden Orten zurückgegeben.

Bei Verwendung von „Text Search (New)“ werden Informationen zu verschiedenen Orten auf Grundlage eines Textstrings zurückgegeben, z. B. „Pizza in München“, „Schuhgeschäfte in der Nähe von Hamburg“ oder „Hauptstraße 123“. Der Dienst gibt eine Liste mit Orten zurück, die dem Textstring und ggf. der festgelegten Standortgewichtung entsprechen. Mit „Text Search (New)“ können Sie anhand eines Typs nach Orten suchen. Die Ergebnisse lassen sich nach Kriterien wie Öffnungszeiten und Bewertung filtern. Außerdem können Sie sie auf einen bestimmten Standort beschränken oder eine entsprechende Gewichtung festlegen.

Wenn Sie „Text Search (New)“ verwenden möchten, müssen Sie „Places API (New)“ in Ihrem Google Cloud-Projekt aktivieren. Weitere Informationen

Orte per Textabfrage suchen

Rufen Sie searchByText auf, um mithilfe einer Textabfrage oder Telefonnummer eine Liste von Orten zu erhalten. Geben Sie die Suchparameter in einer Anfrage an und rufen Sie dann searchByText() auf. Die Ergebnisse werden in Form einer Liste von Place-Objekten zurückgegeben, aus der Sie Ortsdetails abrufen können. Das folgende Snippet zeigt ein Beispiel für eine Anfrage und einen Aufruf von searchByText:

TypeScript

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

const { places } = await Place.searchByText(request);
  • Geben Sie eine Textanfrage oder Telefonnummer für die Suche mit dem Parameter textQuery an.
  • Verwenden Sie den Parameter fields (erforderlich), um eine durch Kommas getrennte Liste eines oder mehrerer Datenfelder in der Camel-Case-Schreibweise anzugeben. Die von Ihnen angeforderten Felder bestimmen den Preis der Anfrage. Weitere Informationen finden Sie unter Datenfelder auswählen.
  • Verwenden Sie den Parameter includedType, um nur Ergebnisse des angegebenen Typs zurückzugeben.
  • Verwenden Sie entweder locationBias oder locationRestriction, um die Ergebnisse der Textsuche auf eine bestimmte Region zu beschränken oder eine entsprechende Gewichtung festzulegen.
Vollständige Liste der Properties

Falls die Abfrage eine Telefonnummer enthält, muss der Regionsparameter festgelegt werden. Wenn Sie beispielsweise mit einer Telefonnummer nach einem Ort in Japan suchen und die anfragende Domain jp ist, müssen Sie den region-Parameter auf „jp“ festlegen. Wenn region in der Anfrage weggelassen wird, wird standardmäßig die Region „USA“ („us“) verwendet.

Die Ergebnisse werden in Form einer Liste von Place-Objekten zurückgegeben, aus der Sie Ortsdetails abrufen können.

Beispiel

Im folgenden Beispiel wird searchByText mit dem angegebenen Abfragetext aufgerufen. Die Ergebnisse werden auf einer Karte in Form von anklickbaren Markierungen dargestellt.

TypeScript

let map: google.maps.Map;
let markers: Record<string, google.maps.marker.AdvancedMarkerElement> = {};
let infoWindow: google.maps.InfoWindow;

async function init() {
    const [{ Map, InfoWindow }, { ControlPosition }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('core'),
    ]);

    const center = { lat: 37.4161493, lng: -122.0812166 };
    map = new Map(document.getElementById('map')!, {
        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')!;
    map.controls[ControlPosition.TOP_LEFT].push(card);

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

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

    infoWindow = new InfoWindow();
}

async function findPlaces(query: string) {
    const [{ Place }, { AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('places'),
        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,
        locationRestriction: map.getBounds(),
        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: google.maps.places.Place) => {
            const marker = new AdvancedMarkerElement({
                map,
                position: place.location,
                title: place.displayName,
                gmpClickable: true,
            });
            markers[place.id] = marker;

            marker.addEventListener('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.
function updateInfoWindow(
    title: string | Element | null,
    content: string | Element | null,
    anchor: google.maps.marker.AdvancedMarkerElement
) {
    infoWindow.setContent(content);
    infoWindow.setHeaderContent(title);
    infoWindow.open({
        map,
        anchor,
        shouldFocus: false,
    });
}

void init();

JavaScript

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

async function init() {
    const [{ Map, InfoWindow }, { ControlPosition }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('core'),
    ]);

    const center = { lat: 37.4161493, lng: -122.0812166 };
    map = new Map(document.getElementById('map'), {
        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[ControlPosition.TOP_LEFT].push(card);

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

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

    infoWindow = new InfoWindow();
}

async function findPlaces(query) {
    const [{ Place }, { AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('places'),
        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,
        locationRestriction: map.getBounds(),
        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,
                gmpClickable: true,
            });
            markers[place.id] = marker;

            marker.addEventListener('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.
function updateInfoWindow(title, content, anchor) {
    infoWindow.setContent(content);
    infoWindow.setHeaderContent(title);
    infoWindow.open({
        map,
        anchor,
        shouldFocus: false,
    });
}

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

#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: 0.5rem;
    width: auto;
    padding: 0.6rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: #fff;
    background-color: #2563eb;
    border: none;
    border-radius: 0.375rem;
    cursor: pointer;
    transition: background-color 0.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>
        <script>
            // prettier-ignore
            (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: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <div id="text-input-card">
            <input
                type="text"
                id="text-input"
                placeholder="Search for a place" />
            <input type="button" id="text-input-button" value="Search" />
        </div>
        <div id="map"></div>
    </body>
</html>

Datenfelder auswählen

Die von Ihnen angeforderten Felder bestimmen den Preis jeder Suchanfrage. Die Anfrage wird einmal in Rechnung gestellt, und zwar mit der höchsten SKU unter den angeforderten Feldern. Wenn Sie beispielsweise reviews zu fields hinzufügen, wird die gesamte Anfrage als „Text Search Enterprise + Atmosphere“ abgerechnet.

Wenn Sie Suchanfragen auf Text Search Pro beschränken möchten, fordern Sie nur die Felder an, die in Ihren Suchergebnissen angezeigt werden, z. B. id, displayName, formattedAddress und location.

Wenn ein Nutzer einen Ort auswählt, rufen Sie fetchFields() für diesen Ort auf, um Felder wie reviews, nationalPhoneNumber oder websiteURI abzurufen. Jeder fetchFields()-Aufruf ist eine separate „Place Details“-Anfrage, die mit der höchsten SKU unter den angeforderten Feldern abgerechnet wird. Ob Sie mit diesem Ansatz Geld sparen, hängt davon ab, wie viele Orte Ihre Nutzer öffnen.

Felder, die die einzelnen SKUs auslösen

  • Die folgenden Felder lösen die SKU „Text Search Essentials (IDs Only)“ aus:

    id

  • Die folgenden Felder lösen die SKU „Text Search Pro“ aus:

    accessibilityOptions
    addressComponents
    adrFormatAddress
    businessStatus
    displayName
    formattedAddress
    googleMapsUri
    iconBackgroundColor
    location
    photos
    plusCode
    svgIconMaskURI
    types
    utcOffsetMinutes
    viewport

  • Die folgenden Felder lösen die Text Search Enterprise-SKU aus:

    internationalPhoneNumber
    nationalPhoneNumber
    priceLevel
    rating
    regularOpeningHours
    userRatingCount
    websiteURI

  • Die folgenden Felder lösen die SKU Text Search Enterprise + Atmosphere aus:

    allowsDogs
    editorialSummary
    evChargeOptions
    fuelOptions
    hasCurbsidePickup
    hasDelivery
    hasDineIn
    hasLiveMusic
    hasMenuForChildren
    hasOutdoorSeating
    hasRestroom
    hasTakeout
    hasWifi
    isGoodForChildren
    isGoodForGroups
    isGoodForWatchingSports
    isReservable
    parkingOptions
    paymentOptions
    reviews
    servesBeer
    servesBreakfast
    servesBrunch
    servesCocktails
    servesCoffee
    servesDessert
    servesDinner
    servesLunch
    servesVegetarianFood
    servesWine

Die SKU für jedes Feld finden Sie unter Datenfelder der Klasse „Place“.