RobinCirex
RobinCirex

Reputation: 43

Google Places API, get more than 20-60 results

The title already gives it away. I want to get a list of all restaurants in my area. Google Places limits "NearbySearch" requests to a maximum of 20 (60 with pagination). What approach would you guys use to get more than 60 results.

I'm currently thinking about something like this:

const searchRadius = 5000; 
const center = { lat: 50.262, lng: 10.970 };
const step = 0.05; 

const searches = [];
for (let latOffset = -0.2; latOffset <= 0.2; latOffset += step) {
  for (let lngOffset = -0.2; lngOffset <= 0.2; lngOffset += step) {
    searches.push({
      location: { lat: center.lat + latOffset, lng: center.lng + lngOffset },
      radius: searchRadius,
    });
  }
}

And then sort the request by distance with a very small radius. However, this feels kind of hacky. I know this topic has been discussed alot and there are a lot of other threads, but it has been years since the last post so I was wondering if there is maybe anything new. I couldn't find anything after hours of going through Googles Documentation and stackoverflow, but I thought I'd give it a shot.

Edit:

I wrote this code, which basically uses the grid approach I already posted, but I enhanced it a bit. I made it so that if the request actually returns more than the limit, the step is repeated but smaller.

async function fetchAllPages(dbConnection, params) {
    let nextPageToken = null;
    let totalResults = 0;

    let anyInGermany = false;
    do {
        try {
            if (nextPageToken) {
                await new Promise((resolve) => setTimeout(resolve, 2000));
                params.pagetoken = nextPageToken;
            }

            const response = await client.placesNearby({params});
            const results = response.data.results;
            totalResults += results.length;

            for (const place of results) {
                const details = await getPlaceDetails(place.place_id);

                if (details && details.address.includes('Germany')) {
                    anyInGermany = true;
                    await saveToDatabase(dbConnection, details);
                } else {
                    console.log(`Übersprungen (nicht in Deutschland): ${place.name}, ${details.address}`);
                }
            }

            nextPageToken = response.data.next_page_token || null;
        } catch (error) {
            console.error(`Fehler beim Abrufen von Seiten:`, error.message);
            nextPageToken = null;
        }
    } while (nextPageToken);

    if(!anyInGermany)
        await saveInvalidCoordinate(dbConnection, params.location.lat, params.location.lng)

    return totalResults;
}

async function requestWithDynamicStep(dbConnection, lat, lng, step) {
    let currentStep = step;
    let totalResults = 0;

    while (currentStep >= MIN_STEP) {
        const coordKey = `${lat},${lng}`;

        if (invalidCoordinatesCache.has(coordKey)) {
            console.log(`Überspringe ungültige Koordinaten: ${lat}, ${lng}`);
            return;
        }

        console.log(`Suche Orte bei Lat: ${lat}, Lng: ${lng}, Schrittweite: ${currentStep}...`);

        const params = {
            location: {lat, lng},
            rankby: 'distance',
            type: 'restaurant',
            key: apiKey,
        };

        totalResults = await fetchAllPages(dbConnection, params);

        if (totalResults >= MAX_RESULTS) {
            console.log(`Limit erreicht (${totalResults} Treffer). Schrittweite verkleinern...`);
            currentStep /= 2;
        } else if (totalResults === 0) {

        } else {
            break;
        }
    }

    if (currentStep < MIN_STEP) {
        console.log(`Minimale Schrittweite erreicht bei Lat: ${lat}, Lng: ${lng}`);
    }
}

async function searchPlacesAcrossGermany() {
    const dbConnection = await mysql.createConnection(dbConfig);

    await loadInvalidCoordinates(dbConnection);

    for (let lat = GERMANY_BOUNDS.south; lat <= GERMANY_BOUNDS.north; lat += initialStep) {
        for (let lng = GERMANY_BOUNDS.west; lng <= GERMANY_BOUNDS.east; lng += initialStep) {
            await requestWithDynamicStep(dbConnection, lat, lng, initialStep);
        }
    }

    await dbConnection.end();
    console.log('Fertig mit der Suche und Speicherung!');
}

Upvotes: 1

Views: 81

Answers (1)

miguev
miguev

Reputation: 4865

The Places APIs were never provided to get a list of all restaurants (or any other type of place) in my area (or anywhere). If you are interested, there is a feature request for this in https://issuetracker.google.com/35826799

However, in the meantime, Google did recently launch a new Places Insights API which may be a better (or good enough) fit for this or similar purposes.

Upvotes: 0

Related Questions