loading...

Azure Search SDK in Government

documentednerd profile image Kevin Mack Originally published at welldocumentednerd.com on ・3 min read

So I’ve been working on a demo project using Azure Search, and if you’ve followed this blog for a while you know. I do a lot of work that requires Azure Government. Well recently I needed to implement a search that would be called via an Azure Function and require the passing of latitude and longitude to facilitate the searching within a specific distance. So I started to build my azure function using the SDK. And what I ended up with looked a lot like this:

Key Data elements:

First to be able to interact with my search service I need to install the following nuget package:

Microsoft.Azure.Search

And upon doing so, I found so pretty good documentation herefor building the search client. So I built out a GeoSearchProvider class that looked like the following:

NOTE: I use a custom class called IConfigurationProvider which encapsulates my configuration store, in most cases its KeyVault, but it can be a variety of other options.

public class GeoSearchProvider : IGeoSearchProvider { IConfigurationProvider \_configurationProvider; public GeoSearchProvider(IConfigurationProvider configurationProvider) { \_configurationProvider = configurationProvider; } public async Task<DocumentSearchResult<SearchResultModel>> RunSearch(string text, string latitude, string longitude, string kmdistance, Microsoft.Extensions.Logging.ILogger log) { if (String.IsNullOrEmpty(kmdistance)) { kmdistance = await \_configurationProvider.GetSetting("SearchDefaultDistance"); } var serviceName = await \_configurationProvider.GetSetting("SearchServiceName"); var serviceApiKey = await \_configurationProvider.GetSetting("SearchServiceApiKey"); var indexName = await \_configurationProvider.GetSetting("SearchServiceIndex"); SearchIndexClient indexClient = new SearchIndexClient(serviceName, indexName, new SearchCredentials(serviceApiKey)); var parameters = new SearchParameters() { Select = new[] { "...{list of fields}..." }, Filter = string.Format("geo.distance(location, geography'POINT({0} {1})') le {2}", latitude, longitude, kmdistance) }; var logmessage = await \_configurationProvider.GetSetting("SearchLogMessage"); try { var results = await indexClient.Documents.SearchAsync<SearchResultModel>(text, parameters); log.LogInformation(string.Format(logmessage, text, latitude, longitude, kmdistance, results.Count.ToString())); return results; } catch (Exception ex) { log.LogError(ex.Message); log.LogError(ex.StackTrace); throw ex; } } }

The above code seems pretty straight forward and will run just fine to get back my search results. I even built in logic so that if I don’t give it a distance, it will take a default from the configuration store, pretty slick.

And I pretty quickly ran into a problem, and that error was “Host Not found”.

And I racked my brain on this for a while before I discovered the cause. By default, the Azure Search SDK, talks to Commercial. Not Azure Government, and after picking through the documentation I found this. There is a property called DnsSuffix, which allows you to put in the suffix used for finding the search service. By default it is “search.windows.net”. I changed my code to the following:

public class GeoSearchProvider : IGeoSearchProvider { IConfigurationProvider \_configurationProvider; public GeoSearchProvider(IConfigurationProvider configurationProvider) { \_configurationProvider = configurationProvider; } public async Task<DocumentSearchResult<SearchResultModel>> RunSearch(string text, string latitude, string longitude, string kmdistance, Microsoft.Extensions.Logging.ILogger log) { if (String.IsNullOrEmpty(kmdistance)) { kmdistance = await \_configurationProvider.GetSetting("SearchDefaultDistance"); } var serviceName = await \_configurationProvider.GetSetting("SearchServiceName"); var serviceApiKey = await \_configurationProvider.GetSetting("SearchServiceApiKey"); var indexName = await \_configurationProvider.GetSetting("SearchServiceIndex"); var dnsSuffix = await \_configurationProvider.GetSetting("SearchSearchDnsSuffix"); SearchIndexClient indexClient = new SearchIndexClient(serviceName, indexName, new SearchCredentials(serviceApiKey)); indexClient.SearchDnsSuffix = dnsSuffix; var parameters = new SearchParameters() { Select = new[] { "...{list of fields}..." }, Filter = string.Format("geo.distance(location, geography'POINT({0} {1})') le {2}", latitude, longitude, kmdistance) }; //TODO - Define sorting based on distance var logmessage = await \_configurationProvider.GetSetting("SearchLogMessage"); try { var results = await indexClient.Documents.SearchAsync<SearchResultModel>(text, parameters); log.LogInformation(string.Format(logmessage, text, latitude, longitude, kmdistance, results.Count.ToString())); return results; } catch (Exception ex) { log.LogError(ex.Message); log.LogError(ex.StackTrace); throw ex; } } }

And set the “SearchSearchDnsSuffix” to “search.azure.us” for government, and it all immediately worked.

Discussion

pic
Editor guide