Crawling (getting data into Azure Search)
On the indexing side of things I was able to achieve this in Sitecore 9 by taking the following steps:
- Create a custom index configuration for my customer Index. I didn't want to disrupt the standard out the box indexes.
- Defined a computed field that read in a Lat Long from my Sitecore Items. The computed field returned a GeoJson object:
using System.Collections.Generic;
using Newtonsoft.Json;
public class GeoJson
{
[JsonProperty(PropertyName = "coordinates")]
public List<double> Coordinates { get; set; }
[JsonProperty(PropertyName = "type")]
public string Type { get; set; }
}
- In your index configuration override the standard indexFieldStorageValueFormatter with your own implementation. Your implementation will override CloudIndexFieldStorageValueFormatter.cs and the method FormatValueForIndexStorage:
public override object FormatValueForIndexStorage(object value, string fieldName)
{
object obj = value;
if (!string.IsNullOrWhiteSpace(fieldName) &&
fieldName.ToLower().StartsWith("geo_"))
return obj;
return base.FormatValueForIndexStorage(value, fieldName);
}
This is necessary because EDM.GeographyPoint is not supported and native EDM data type by Sitecore. Without this Sitecore's code will throw an exception when indexing.
- Added a new map to the custom index configuration.
<cloudTypeMapper ref="contentSearch/indexConfigurations/defaultCloudIndexConfiguration/cloudTypeMapper">
<maps hint="raw:AddMap">
<map type="AAA.Foundation.Geo.Models.GeoJson, AAA.Foundation.Geo" cloudType="Edm.GeographyPoint"/>
</maps>
</cloudTypeMapper>
- Added a new cloudTypeConfiguration for my custom index
<cloudTypeConfiguration ref="contentSearch/indexConfigurations/defaultCloudIndexConfiguration/cloudTypeConfiguration">
<types hint="raw:AddType">
<type cloudType="Edm.GeographyPoint" cloudFieldNameFormat="{0}_g"/>
</types>
</cloudTypeConfiguration>
- Add in a field map to your custom index configuration. This must match the computed field name added in an earlier step.
<fieldMap ref="contentSearch/indexConfigurations/defaultCloudIndexConfiguration/fieldMap">
<fieldNames hint="raw:AddFieldByFieldName">
<field fieldName="geo_location" cloudFieldName="geo_location" searchable="NO" retrievable="YES" facetable="NO" filterable="YES" sortable="YES" boost="1f" type="AAA.Foundation.Geo.Models.GeoJson, AAA.Foundation.Geo" settingType="Sitecore.ContentSearch.Azure.CloudSearchFieldConfiguration, Sitecore.ContentSearch.Azure" />
</fieldNames>
</fieldMap>
Searching (getting data out of Azure Search)
Although I did find a way to extend the Sitecore Azure Search Provider it did not support the OrderBy clause which is very useful for fast queries in spatial searches.
The best solution I found was the use the Azure Search DLL library directly (Microsoft.Azure.Search).
With this you can connect directly to your index and use the syntax as follows:
$"geo.distance({fieldName}, geography'POINT({coordinate.Longitude} {coordinate.Latitude})') le {settingsSearchRadius}"
This will find all results from a particular location up to a given radius.
A full searching example can be found here.