Search code examples
azuresearchgeospatialazure-cognitive-searchspatial-query

Spatial Search in Azure Search .NET client API


How can I do a spatial search using the Azure Search .NET SDK? The question has been answered for the REST API here:

SO thread for REST API

How can I do the exact same using the .NET client API?

To be more specific:

How do I need to define the according property on the Document class? How can I query documents where the property value lies within a defined circle (center, radius)?


Solution

  • Just made it work on my last try (as always, just after posting the question...)

    Reference the Nuget package Microsoft.Spatial

    Use GeographyPoint as property type in class definition:

    public class MyDocument
    {
        [IsFilterable, IsSortable]
        public Microsoft.Spatial.GeographyPoint Location { get; set; }
    }
    

    Create a document like this:

    var lat = ...; //Latitude
    var lng = ...; //Longitude
    var myDoc = new MyDocument();
    
    myDoc.Location = GeographyPoint.Create(lat, lng);
    // Upload to index
    

    Query like this:

    // center of circle to search in
    var lat = ...;
    var lng = ...;
    // radius of circle to search in
    var radius = ...;
    
    // Make sure to use invariant culture to avoid using invalid decimal separators
    var latString = lat.ToString(CultureInfo.InvariantCulture);
    var lngString = lng.ToString(CultureInfo.InvariantCulture);
    var radiusString = radius.ToString(CultureInfo.InvariantCulture);
    
    var searchParams = new SearchParameters();
    searchParams.Filter = $"geo.distance(location, geography'POINT({lngString} {latString})') lt {radius}";
    
    var searchResults = index.Documents.Search<Expert>(keyword, searchParams);
    var items = searchResults.Results.ToList();
    

    Note that location corresponds to the property name Location and needs to be replaced accordingly if your property is named differently. To sort results by distance, also set OrderBy-property of search parameters:

    searchParams.OrderBy = new List<string> { $"geo.distance(location, geography'POINT({lngString} {latString})') asc" };
    

    It took me a while to find out that when defining the point in the query:

    geography'POINT({lngString} {latString})'
    

    The parameter order is (Longitude, Latitude) other than in most other conventions (i.e. Google maps API uses other way around).