Rainbolt
Rainbolt

Reputation: 3660

Why does Google Place Search only return one result for this address?

I'm trying to geocode an address using the Google API. Geocode here means given an address, figure out the latitude and longitude. The addresses coming through my system tend to have typos and missing components. Google recommends using the Places API for ambiguous addresses like mine.

The service is especially useful for making ambiguous address queries in an automated system, and non-address components of the string may match businesses as well as addresses. Examples of ambiguous address queries are incomplete addresses, poorly formatted addresses, or a request that includes non-address components such as business names.

I included the script on the page like so:

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>

And then I made a request:

var mapElem = document.getElementById('map');
var service = new google.maps.places.PlacesService(mapElem);
var bounds = { 
    north: 50, 
    south: 20, 
    east: -60, 
    west: -130 
};
var searchOptions = { 
    bounds: bounds, 
    query: '100 Broadway, Tyler, TX' 
};
service.textSearch(searchOptions, (results, status) => { 
    console.log(results, status); 
});

The problem is that there are two different 100 Broadway in Tyler, TX (100 N Broadway and 100 S Broadway), but the API only returns 100 N Broadway. I need the results to include both results so that the user can choose the correct one. How do I accomplish this?

I also tried using findPlaceFromQuery() and nearbySearch(). The former also only returned one result, and the latter didn't have a place to put the address (I think the latter is intended more for finding all of a type of thing in a given area, such as restaurants).

Upvotes: 0

Views: 436

Answers (1)

geocodezip
geocodezip

Reputation: 161324

Autocomplete returns both options, you can let your user choose the correct one.

screenshot of autocomplete showing results

As an aside, a search for "100 Broadway Tyler, TX" returns just "100 North Broadway", while a search for "100 S Broadway Tyler, TX" returns both results. That seems like a bug either in the API or in the data used by the API.

proof of concept fiddle

screenshot of both results from the places service

code snippet (with place search for 100 S Broadway, Tyler TX; and autocomplete):

"use strict";

// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCPJpjD-qcR_yIxJnS8maR5W9KB0E3EzYI&libraries=places">
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: {
      lat: -33.8688,
      lng: 151.2195
    },
    zoom: 13
  });
  const card = document.getElementById("pac-card");
  const input = document.getElementById("pac-input");
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
  const request = {
    query: "100 S Broadway Tyler, TX",
    fields: ["name", "geometry"]
  };
  let service = new google.maps.places.PlacesService(map);
  service.findPlaceFromQuery(request, (results, status) => {
    if (status === google.maps.places.PlacesServiceStatus.OK) {
      console.log("results.length=" + results.length);
      let bounds = new google.maps.LatLngBounds();
      for (let i = 0; i < results.length; i++) {
        console.log(results[i]);
        let marker = createMarker(results[i]);
        bounds.extend(marker.getPosition())
      }
      console.log(bounds.getCenter().toUrlValue(6));
      google.maps.event.addListenerOnce(map, 'zoom_changed', function() {
        map.setZoom(map.getZoom() - 1);
      })
      map.fitBounds(bounds);
    }
  });


  function createMarker(place) {
    const marker = new google.maps.Marker({
      map,
      position: place.geometry.location
    });
    console.log(place.name + "<br>" + place.formatted_address);
    google.maps.event.addListener(marker, "click", () => {
      infowindow.setContent(place.name);
      infowindow.open(map, marker);
    });
    return marker;
  }
  const autocomplete = new google.maps.places.Autocomplete(input); // Bind the map's bounds (viewport) property to the autocomplete object,
  // so that the autocomplete requests use the current map bounds for the
  // bounds option in the request.

  autocomplete.bindTo("bounds", map); // Set the data fields to return when the user selects a place.

  autocomplete.setFields(["address_components", "geometry", "icon", "name"]);
  const infowindow = new google.maps.InfoWindow();
  const infowindowContent = document.getElementById("infowindow-content");
  infowindow.setContent(infowindowContent);
  const marker = new google.maps.Marker({
    map,
    anchorPoint: new google.maps.Point(0, -29)
  });
  autocomplete.addListener("place_changed", () => {
    infowindow.close();
    marker.setVisible(false);
    const place = autocomplete.getPlace();

    if (!place.geometry) {
      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      window.alert("No details available for input: '" + place.name + "'");
      return;
    } // If the place has a geometry, then present it on a map.

    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    let address = "";

    if (place.address_components) {
      address = [
        (place.address_components[0] &&
          place.address_components[0].short_name) ||
        "",
        (place.address_components[1] &&
          place.address_components[1].short_name) ||
        "",
        (place.address_components[2] &&
          place.address_components[2].short_name) ||
        ""
      ].join(" ");
    }

    infowindowContent.children["place-icon"].src = place.icon;
    infowindowContent.children["place-name"].textContent = place.name;
    infowindowContent.children["place-address"].textContent = address;
    infowindow.open(map, marker);
  }); // Sets a listener on a radio button to change the filter type on Places
  // Autocomplete.

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

#description {
  font-family: Roboto;
  font-size: 15px;
  font-weight: 300;
}

#infowindow-content .title {
  font-weight: bold;
}

#infowindow-content {
  display: none;
}

#map #infowindow-content {
  display: inline;
}

.pac-card {
  margin: 10px 10px 0 0;
  border-radius: 2px 0 0 2px;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  outline: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  background-color: #fff;
  font-family: Roboto;
}

#pac-container {
  padding-bottom: 12px;
  margin-right: 12px;
}

.pac-controls {
  display: inline-block;
  padding: 5px 11px;
}

.pac-controls label {
  font-family: Roboto;
  font-size: 13px;
  font-weight: 300;
}

#pac-input {
  background-color: #fff;
  font-family: Roboto;
  font-size: 15px;
  font-weight: 300;
  margin-left: 12px;
  padding: 0 11px 0 13px;
  text-overflow: ellipsis;
  width: 400px;
}

#pac-input:focus {
  border-color: #4d90fe;
}

#title {
  color: #fff;
  background-color: #4d90fe;
  font-size: 25px;
  font-weight: 500;
  padding: 6px 12px;
}
<!DOCTYPE html>
<html>

<head>
  <title>Place Autocomplete</title>
  <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&v=weekly" defer></script>
  <!-- jsFiddle will insert css and js -->
</head>

<body>
  <div class="pac-card" id="pac-card">
    <div>
      <div id="title">
        Autocomplete search
      </div>
    </div>
    <div id="pac-container">
      <input id="pac-input" type="text" placeholder="Enter a location" value="100 Broadway, Tyler, TX " />
    </div>
  </div>
  <div id="map"></div>
  <div id="infowindow-content">
    <img src="" width="16" height="16" id="place-icon" />
    <span id="place-name" class="title"></span><br />
    <span id="place-address"></span>
  </div>
</body>

</html>

Upvotes: 1

Related Questions