3

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)?

Marc
  • 12,706
  • 7
  • 61
  • 97

2 Answers2

4

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).

Marc
  • 12,706
  • 7
  • 61
  • 97
0

Although it will work, the accepted answer is incorrect. You do not need a add a reference to Microsoft.Spatial and use the GeographicalPoint type.

You simply need to create a class that will serialize to a GeoJSON geography type:

{ "type": "Point", "coordinates": [125.6, 10.1] }

In C#:

public class GeoPoint
{
    [JsonProperty("type")]
    public string Type { get; } = "Point";

    [JsonProperty("coordinates")]
    public double[] Coordinates { get; set; } = new double[0];
}

As as a property in your indexed class:

    [IsSearchable, IsFilterable]
    [JsonProperty(PropertyNames.Location)]
    public GeoPoint Location { get; set; }

**If you're adding this as a new property, you will need to add the property in the Azure portal before re-indexing: enter image description here

Lee Smith
  • 6,339
  • 6
  • 27
  • 34