The Find Service is one of the four core components of the MapPoint Web Service, allowing you to find places, addresses, points of interest around a given place or address, locations based on entity types, and so on. In this chapter, we’ll take an in-depth look at the MapPoint Web Service Find APIs.
Understanding Find APIs
If you remember from our discussion in Chapter 5, the Find Service endpoint is located at the FindService.asmx, and the APIs available for Find Service are exposed via the FindServiceSoapclass in the Web Service proxy (Reference.cs or Reference.vb). TheFindServiceSoapclass contains a number of find-related methods used for finding places, addresses, nearby points, and so on. Table 6-1 shows the methods exposed on theFindServiceSoapclass.
Table 6-1. Methods available on the FindServiceSoap class
Method
Description
Find
Finds geographic locations in a specified data source based on a place name. Returns an array of results as aFindResultsobject. Maximum returned values is 500. Default number of returned results is 25.
FindAddress
Finds geographic locations in a specified data source based on an address. Returns an array of possible results as aFindResultsobject. Maximum returned values is 100. Default number of returned results is 25.
FindByID
Finds points of interest based on entity ID. The found results are returned as aFindResults object.
FindByProperty
Finds points of interest based on predefined or custom properties. This method is independent of the location information such as distance and latitude/longitude. The found results are returned as aFindResultsobject.
Table 6-1. Methods available on the FindServiceSoap class (continued)
Method
Description
FindNearby
Finds points of interest within a specified distance of a given latitude and longitude coordinate; returns an array of found points of interest ordered by proximity to a selected point as a FindResultsobject. Maximum returned values is 500. Default number of returned results is 25.
FindNearRoute
Finds points of interest within a specified distance from a route. The found results are returned as aFindResultsobject.
FindPolygon
Finds polygons in a specified data source, based on aFindPolygonSpecificationobject. The found results are returned as aFindResultsobject.
GetLocationInfo
Finds geographic entities and addresses for a specified latitude and longitude coordinate (also known as reverse geocoding). Returns an array of locations (Locationobjects). Maximum returned values is 250.
ParseAddress
Parses a specified address string and returns anAddressobject.
In this chapter, we will go over these methods in detail; first, let’s look at some basic concepts.
The FindServiceSoapclass contains the methods related to find functionality, such asFind (place),FindAddress,FindNearby, and so on. Choose the appropriate find method based on your application’s needs. All find methods share a common signature pattern as shown in the following example, where XXXcan be an address or a nearby entity):
FindResults FindXXX( FindXXXSpecifiction )
A find method, no matter what type of find it is, always returns the results in the form of the FindResults instance, which tells you how many matches are found for your find query along with the actual location matches. The actual location matches are represented as an array of FindResultclass instances, each of which contains an instance of matched location as aLocationobject that provides information such as latitude/longitude, address, entity type, and the confidence score of the location match. It is important to note thatLocationinstances in MapPoint Web Service expose the actual latitude and longitude information of the physical location and a corresponding best possible map view associated with it.
Unlike the consistent output returned by all find methods, the input argument is unique to each find method type, so the specification corresponding to each find type is represented by specific types. For example, if you are using theFindAddressmethod, use theFindAddressSpecificationobject as an input argument; if you are using theFindNearbymethod, use theFindNearbySpecificationobject as an input argument. Each input specification object contains three core parts:
Data source name
This field is found across all specification objects for all find methods and indicates which data source to use for the find.
Find-type specific arguments
This field is unique to each find method and includes arguments such as input address for an address search, place name for a place search, and so forth.
Optional FindOptionsobject
This field is found across all the specification objects for all find methods and can be used to control the output behavior.
For example, theFindAddressSpecificationobject, which is passed to theFindAddressmethod to find an address, contains the following three fields:
DataSourceName
A string value that represents the data source to be used for the address search (such asMapPoint.NAandMapPoint.EU).
InputAddress
An instance of theAddressclass that represents the input address to be used in the search.
Options
An instance of theFindOptionsclass that can be used to control the behavior of the results returned by any find method. This argument is optional.
Any specification object used in the find method is consistently modeled in this format.
By now, I’m sure you are wondering how theFindOptionsobject can alter the behavior of the results returned by the find method. Let’s look briefly at this object so that you understand its purpose. TheFindOptionsobject contains the following fields:
Range
This field can be used to control the number of returned matches and the starting index of the returned results. For example, if you are searching for a place and your search yields 200 matches, you can request to return only the top 10 results. Along the same lines, you can also request a range of results starting with any valid index (such as from 21 to 30), which is very useful if you are displaying the search results from multiple pages (the typical pagination feature for displaying data). This field is of typeFindRange.
ResultMask
By default, all find methods return latitude/longitude, entity type information, address, and best map view information for each matched location of the input query. You can use this field to mask the unwanted information returned from a find method. For example, if you are searching for a place and looking only for latitude/longitude information, you can prevent the find method from returning any other information using this mask. TheResultMaskfield is of typeFindResultMaskand is an enumeration.
SearchContext
This field indicates the entity ID within which you want to perform your search. In this case, the entity ID represents a geographic area to which you want to limit your search. Assigning an entity to provide a search context returns more relevant matches faster. This field is of typeInteger.
ThresholdScore
Each result returned by any find method contains a score indicating the level of confidence in the match. Using this field, you can filter out the low-confidence results below the specifiedThresholdScore. This field is of typeDouble, and the valid values are between zero and one (low confidence to high confidence).
Using theFindOptionsobject, you can tailor the results returned by the find method according to your application’s needs. There is one more interesting tidbit you may want to know about theFindOptionsobject: when you use it in your find method calls, you actually positively impact the performance (and possibly the economics) of your application. I will discuss the details at the end of this chapter in the section on optimizing your find calls performance.
Now that you know the anatomy of the Find Service, let’s look briefly at entities and the entity relationships model in MapPoint Web Service before we get into coding aspects of the Find Service.
Entities in MapPoint Web Service represent real things (e.g., countries, cities, landmarks, schools) that exist in the real world. All entities are first-class citizens in the world of MapPoint Web Service; they have type definitions, carry their own identities, enjoy entity-level find capabilities, maintain relationships, and in some cases even persist their identity across different versions of MapPoint Web Service.
Before I get into too many details, here is an example to help you understand this concept. Consider the United States: in MapPoint Web Service, the country is an entity with entity ID 244; the states contained within it are represented as children entities to the United States entity. Counties, cities, and towns within these states are represented as the children entities to the state entities; this parent-child relationship continues down to things like bridges, roads, parks, and schools. Figure 6-1 summarizes this discussion by showing the entity relationships for the town of Redmond, WA.
How do all the entities and entity relationships defined in MapPoint Web Service help you? The short answer is that you can issue smarter and more focused find queries to find things that suit your needs. Many applications require you to drill down into the subgeographic areas starting with a larger coverage. To continue with our United States example, you may want to develop an application where your customers start with the United States, go to the 50 states in the United States, pick a state
Figure 6-1.Entity parent-child relationships
and get all counties, pick a county and get all cities, and pick a city and get all interested entities within it. Entities are used to issue queries with limited geographic context (such as all states within the United States). You can also add your own custom entity types (or points of interest) that allow you to find places using the entities and entity relationships.
Programmatically, all entities are represented by theEntityclass, and the definition of an entity type is represented by theEntityType class. TheEntityTypeobjects define the schema of an entity type, including the name, parent, and valid properties of an entity type.
Each physical entity represented using theEntityclass has anID, aDisplayName, which is a long descriptive name, and a common shortName. AnEntityobject also indicates the type of entity using theTypeNamefield (which is astring); this type name maps to a correspondingEntityTypeobject. Finally, anEntityobject exposes a collection of properties specific to that entity type as an array ofEntityPropertyValueobjects. TheEntityPropertyValueobject is a simple name value pair that gives you the name and value of the property. If you know an entity’s properties, you can issue queries to find entities by their properties—we will look at this concept later in this chapter.
If you find the concepts ofEntityTypeandEntityconfusing, think of it this way: anEntityTypedefines the schema, and anEntityrepresents the instance of a “thing” with that schema (similar to the difference between a class and an object). For example, the entity typePopulatedPlacedefines the schema and parent-child relationships for geographic entities such as cities, towns, and villages; the entity typePopulatedPlaceis represented by theEntityType class programmatically. The city of Paris is an entity of typePopulatedPlace, so the actual city is represented by anEntityobject programmatically with aTypeNameofPopulatedPlace.
Because entities in MapPoint Web Service are real things, they are contained in corresponding data sources for any given geographic extent. For example, if you consider the North American map data source MapPoint.NA, entities within the United States, Canada, Mexico, and Puerto Rico are contained in this data source. The only way to get to these entities is by knowing which entity types are supported by a particular data source. To find out which entity types are supported by a given data source, use theCommonServiceSoapmethod to get a list of the entity types supported by different data sources.
Getting all supported entity types within a data source
You can get a list of entity types supported by a specific data source using the CommonServiceSoap.GetEntityTypes method, which takes the data source name as an input argument and returns an array ofEntityTypeobjects. The following code snippet shows how to get all entity types defined in theMapPoint.NAdata source:
//Define an instance of CommonServiceSoap class CommonServiceSoap commonService = new CommonServiceSoap(); //Assign credentials . . . //Define a local entitytypes array EntityType[] entityTypes; //Datasource in question string datasource = "MapPoint.NA"; //Get all entity types using the GetEntityTypes method entityTypes = commonService.GetEntityTypes(datasource); //Now loop through each entity display the name, parent foreach(EntityType et in entityTypes) { Console.WriteLine(et.Name); Console.WriteLine(et.Definition); Console.WriteLine(et.ParentName); }
Along the same lines, you can also get all entity type definitions for all data sources in MapPoint Web Service environment:
//Create an instance of common service soap CommonServiceSoap commonService = new CommonServiceSoap(); //Assign credentials . . . DataSource[] dataSources; dataSources = commonService.GetDataSourceInfo(null); foreach (DataSource ds in dataSources) { String datasource = ds.Name; //Now get entity type info for this data source //Define a local entitytypes array EntityType[] entityTypes; //Datasource in question //Get all entity types using the GetEntityTypes method entityTypes = commonService.GetEntityTypes(datasource); //Now loop through each entity display the name, parent foreach(EntityType et in entityTypes) { Console.WriteLine(et.Name); Console.WriteLine(et.Definition); Console.WriteLine(et.ParentName); } }
I use theCommonServiceSoap.GetDataSourceInfomethod to get a list of data sources and then theCommonServiceSoap.GetEntityTypesmethod to get a list of entity types defined in each data source.
Once you know the names of the entity types, you can use the Find APIs, which we will see in detail later in the chapter, to customize the find queries to find only particular entity types.
Please check back next week for the continuation of this article.