Making API faces at Google Maps and Places
Introduction
I recently finished a 1st phase of a Google Maps/Places project for a client,and was amazed at some of the things Google leaves out of their API. Here are some quick notes about what I ran into.
The App
My app enables searching within an area, by keyword and/or place type. You can edit the shape of the search area by tweaking a polygon. Some fields from the search results are saved to a .csv file, so the places can be used in a spreadsheet.
I am not free to post the source to this app. I’m just passing along a couple of the things I ran into…
60 Results — That’s All For You!
One of the first things you may notice when working with the Google Places Search API is that you can only retrieve the first 60 results. Further, this is chunked, so you get the first 20, and then if you see a token for 20 more, you get the 2nd batch of 20, and then the same thing for the 3rd batch.
Suggestion #1 to Google: why? Just let me retrieve up to 1000 results at once. Give me an upper limit for PlacesService.nearbySearch() , and then provide one batch of results.
When you define a large search area in a busy city, 60 results means that you will miss a lot of places.
Before going on, I should note that there are two ways to tell the Google Places Nearby search about the size of an area that you want to search:
- by radius (from client and server APIs)
- by rectangular LatLng bounds (client API only)
For a small area, the radius is useful. When I pondered what to do with larger areas, there is the idea of breaking up the search into a grid of equally spaced points. This is where a radius is no longer such a good idea:
See what I mean? It’s just Crop Circles :) Even if you overlap them, you will still miss plenty, or you will be making a lot of extra API calls ($$) and having to toss out duplicates. Not good:
At this point, you may be thinking “what if you could search the Places API with an arbitrary polygon, and get back as many results as you want?”
That is a great thought.
After all, it is an API key that we pay for, and, hey, they are Google. If there is one tech company in the world that could figure this stuff out, it would be Google. Right? Couldn’t they just charge a little more for a “polygon request with lots of results?”
I mentioned that you can search with a rectangular boundary (LatLng bounds). This is really helpful. For whatever reason, it can’t be done from the server side (Node.js) API, but it is available to the client.
Suggestion #2 to Google: the Places server side API should have complete feature parity with the client side.
With rectangular search areas, I can do this:
I can break the search up into smaller areas, and ignore the cells that are completely outside of my polygon.
I also have a slider that controls the size of the cells:
The slider gives a lot of control: if you go too small (100 meters) you will be making more API calls than needed ($$). If you go too large, you might go over the 60 result limit, and miss a bunch of results.
It gets even better.
When results come back, I check to see if they are within the search polygon. The ones that are outside of it are ignored. Thankfully, there is a google.maps.geometry.poly.containsLocation() call. (In other words, checking to see if a Lat, Lng coordinate is within a polygon)
However, I did not see a call in the Google geometry library to check for intersecting polygons (to see if a potential search cell intersected with the search polygon).
Really.
I had to seek out code to check for that. There is a good example at https://jsfiddle.net/xzovu9x6/2/ by elrobis. I had to load in a couple of extra JS libs (I’m not up for writing polygon intersection code from scratch)
Suggestion #3 for Google: there should be an call for doPolygonsIntersect(poly1, poly2) in your Geometry library.
Summary
Sorry that I am not at liberty to post code or point to a working demo. Hopefully you get a good idea from the gifs and images I included.
The Google Address Autocomplete, Maps, Places, and Geometry libs will get you far. You can do amazing things with the functionality provided.
However, it is a paid product (keep an eye on your API key quota!), and it does come from some really brilliant people. I was surprised at some of the things that were left out, and what I had to work around.
btw, I am currently available, and would love to do more work in this space.