Searching for POIs with the Bing Phonebook search

The Bing Maps Locations REST API is for geocoding – i.e. finding addresses or places on a map. However, I’ve seen a couple of questions over the last week from people trying to search not for known addresses, but for things – pubs, restaurants, schools, hospitals, and the like. You used to be able to do this kind of search in v6.x of the Bing Maps control using the Find() method, which would search for and then add any matching entities to the map, but this doesn’t exist in the slimmed down v7 control.

Instead, one alternative is to use the Bing API (not the Bing Maps API) to perform a search for the results, and then plot the results on the map. The Bing API exposes a number of REST search services, but the Phonebook search is the one you’re most likely to want to use. To perform a Bing search, you’ll first need a Bing AppId (again, different from your Bing Maps Application Key), which you can sign up for here: http://www.bing.com/developers

You can find a basic sample of the Bing Phonebook search at http://msdn.microsoft.com/en-us/library/dd251030.aspx, which simply outputs the search results into a list. To plot the results on Bing Maps instead, the process is to make a REST request to the Bing phonebook search service and, in the callback function specified, loop through the results and create pushpins at the relevant Latitude and Longitude coordinates and push them on to the map.

For example, in the code below, I search for any pubs that lie within the bounding box of the current map view (refreshes every time the map view changes by listening to the viewchangeend event), and create a pushpin at each location that, when clicked,  displays an Infobox containing the address and phonenumber of the entity.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>Bing Phonebook Search</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
    <script type="text/javascript">
      var map = null;

      function GetMap() {
        // Create a default map
        map = new Microsoft.Maps.Map(
         document.getElementById("mapDiv"),
         {
           credentials: "ENTERYOURBINGMAPSKEY",
           center: new Microsoft.Maps.Location(52.63, 1.3),
           zoom: 17,
           enableSearchLogo: false
         }
        );

         var viewChangeEndHandler = Microsoft.Maps.Events.addHandler(map, 'viewchangeend', ViewChangeEndHandler);   
      }

      function ViewChangeEndHandler(e) {

        var mapCenter = map.getCenter();

        var request = "http://api.bing.net/json.aspx?"
        // Common request fields (required)
            + "AppId=" + "ENTERYOURBINGAPPID"
            + "&Query=Pubs"
            + "&Sources=Phonebook"
        // Common request fields (optional)
            + "&Version=2.0"
            + "&Market=en-us"
            + "&UILanguage=en"
            + "&Latitude=" + mapCenter.latitude
            + "&Longitude=" + mapCenter.longitude
            + "&Radius=100.0"
            + "&Options=EnableHighlighting"
        // Phonebook-specific request fields (optional)
            + "&Phonebook.Count=25"
            + "&Phonebook.Offset=0"
            + "&Phonebook.FileType=YP"
            + "&Phonebook.SortBy=Distance"
        // JSON-specific request fields (optional)
            + "&JsonType=callback"
            + "&JsonCallback=BingPhonebookCallback";

        // Create a new script element
        var script = document.createElement("script");
        script.setAttribute("type", "text/javascript");
        script.setAttribute("src", request);

        // Append the script to the document head
        var dochead = document.getElementsByTagName("head").item(0);
        dochead.appendChild(script);
     }

     function BingPhonebookCallback(response) {
       // If we got a valid, non-null result set
       if (response && response.SearchResponse && response.SearchResponse.Phonebook && response.SearchResponse.Phonebook.Results && response.SearchResponse.Phonebook.Results.length > 0) {

         map.entities.clear();
         
         var results = response.SearchResponse.Phonebook.Results;

         for (var i = 0; i < results.length; i++) {
           var location = new Microsoft.Maps.Location(
             parseFloat(results[i].Latitude),
             parseFloat(results[i].Longitude)
           );

           var pushpin = new Microsoft.Maps.Pushpin(location);
           pushpin.Title = results[i].Title;
           pushpin.Address = results[i].Address;
           pushpin.PhoneNumber = results[i].PhoneNumber;
           pushpin.DisplayUrl = results[i].DisplayUrl;

           Microsoft.Maps.Events.addHandler(pushpin, 'click', function(e) {
           var infoboxOptions = {
             width: 200,
             height: 100,
             showCloseButton: true,
             zIndex: 0,
             offset: new Microsoft.Maps.Point(0, 0),
             showPointer: true,
             title: e.target.Title,
             description: e.target.Address + " " + e.target.PhoneNumber
           };
           var defaultInfobox = new Microsoft.Maps.Infobox(e.target.getLocation(), infoboxOptions);
           map.entities.push(defaultInfobox); 
           });
           
           map.entities.push(pushpin);
         }
       }
     }
    </script>
  </head>
  <body onload="GetMap();">
  <div id='mapDiv' style="position: absolute; top: 0; left: 0; width:800px; height:600px;">
  </div>
  </body>
</html>

And here’s the results, with an Infobox callout showing location details of the best pub quiz in Norwich (held every tuesday night – our regular team name is “Quizteama Aguilera”, BTW):

image

This entry was posted in Bing Maps, Spatial and tagged , . Bookmark the permalink.

10 Responses to Searching for POIs with the Bing Phonebook search

  1. Patric says:

    Hello Alastair,
    thank’s for the code and your work; it works perfect for Germany, but not for France. I changed the data in the market-Tag to ‘fr-Fr’, in the query-Tag to ‘cinema’, but in the result are only ‘Kinos’ on the german part of the map. Any idea why there are no french results available?
    Btw the same happens with the find() method of Version 6.3. Before 02.2011 there were a lot of french results. But then from one day to the other; nothing; no results for france.

    Do you think, it is legal to mix the bing maps with results from Google Places or OSM ??

  2. rbrundritt says:

    Might I suggest a throttled event handler for the viewchangeend event. This might be a good way to reduce the number of requests made without affecting the user experience.

  3. alastaira says:

    Oh sure – I’d always use a throttled handler in a production app, but the point of this code sample is to demonstrate the syntax for using the Bing Phonebook Search API rather than demonstrating how to produce a high performance app😉

  4. Dan BROOKS says:

    Do you have any insight on the query option? Your example uses “Pubs”; is that a category or a keyword search?

    If this is the official documentation, it’s not very helpful
    http://msdn.microsoft.com/en-us/library/dd250916.aspx

    -=Dan=-

    • alastaira says:

      Yeah – the MSDN documentation is shocking. That’s one of the reasons I wrote the blog article😉
      To my knowledge, it’s a keyword search rather than a category search. This being the Bing API, after all (rather than the Bing Maps API), the analogy is to think of the “query” as the thing you would type into the Bing search bar. The difference is that, rather than getting pages full of links to webpages, you get a set of entities with locational information.

      • Dan BROOKS says:

        Any ideas on how-to search for more than one keyword? I tried these combinations:
        Query: “Gyms,Police”
        Query: “Gyms+Police”
        Query: “Gyms Police”
        I would like to plot both Gyms and Police Stations on the map. Tho it seems like this API only allows one keyword search at a time, so I am required to request multiple AJAX calls

        -=Dan=-

  5. Dan BROOKS says:

    Looks like Bing Search API will become Windows Azure
    http://www.bing.com/community/site_blogs/b/developer/archive/2012/04/12/bing-dev-update.aspx

    I will be watching this blog for more details on what the new API will look like.

  6. Pingback: Multinational list of popular first names and surnames? | DL-UAT

  7. sonofabit says:

    was there ever an updated way to do this? it appears PhoneBook is no longer a source type in the latest update since moving to azure… curious to know if there is still a way to do this today…

  8. could you update this with windows Azure

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s