Upgrade to Azure AI Search .NET SDK version 11
If your search solution is built on the Azure SDK for .NET, this article helps you migrate your code from earlier versions of Microsoft.Azure.Search to version 11, the new Azure.Search.Documents client library. Version 11 is a fully redesigned client library, released by the Azure SDK development team (previous versions were produced by the Azure AI Search development team).
All features from version 10 are implemented in version 11. Key differences include:
- One package (Azure.Search.Documents) instead of four
- Three clients instead of two: SearchClient, SearchIndexClient, SearchIndexerClient
- Naming differences across a range of APIs and small structural differences that simplify some tasks
The client library's Change Log has an itemized list of updates. You can review a summarized version in this article.
All C# code samples and snippets in the Azure AI Search product documentation have been revised to use the new Azure.Search.Documents client library.
Why upgrade?
The benefits of upgrading are summarized as follows:
New features are added to Azure.Search.Documents only. The previous version, Microsoft.Azure.Search, is now retired. Updates to deprecated libraries are limited to high priority bug fixes only.
Consistency with other Azure client libraries. Azure.Search.Documents takes a dependency on Azure.Core and System.Text.Json, and follows conventional approaches for common tasks such as client connections and authorization.
Microsoft.Azure.Search is officially retired. If you're using an old version, we recommend upgrading to the next higher version, repeating the process in succession until you reach version 11 and Azure.Search.Documents. An incremental upgrade strategy makes it easier to find and fix blocking issues. See Previous version docs for guidance.
Package comparison
Version 11 consolidates and simplifies package management so that there are fewer to manage.
Version 10 and earlier | Version 11 |
---|---|
Microsoft.Azure.Search Microsoft.Azure.Search.Service Microsoft.Azure.Search.Data Microsoft.Azure.Search.Common |
Azure.Search.Documents package |
Client comparison
Where applicable, the following table maps the client libraries between the two versions.
Client operations | Microsoft.Azure.Search (v10) | Azure.Search.Documents (v11) |
---|---|---|
Targets the documents collection of an index (queries and data import) | SearchIndexClient | SearchClient |
Targets index-related objects (indexes, analyzers, synonym maps | SearchServiceClient | SearchIndexClient |
Targets indexer-related objects (indexers, data sources, skillsets) | SearchServiceClient | SearchIndexerClient (new) |
Caution
Notice that SearchIndexClient exists in both versions, but targets different operations. In version 10, SearchIndexClient creates indexes and other objects. In version 11, SearchIndexClient works with existing indexes, targeting the documents collection with query and data ingestion APIs. To avoid confusion when updating code, be mindful of the order in which client references are updated. Following the sequence in Steps to upgrade should help mitigate any string replacement issues.
Naming and other API differences
Besides the client differences (noted previously and thus omitted here), multiple other APIs have been renamed and in some cases redesigned. Class name differences are summarized in the following sections. This list isn't exhaustive but it does group API changes by task, which can be helpful for revisions on specific code blocks. For an itemized list of API updates, see the change log for Azure.Search.Documents
on GitHub.
Authentication and encryption
Version 10 | Version 11 equivalent |
---|---|
SearchCredentials | AzureKeyCredential |
EncryptionKey (Undocumented in API reference. Support for this API transitioned to generally available in v10, but was only available in the preview SDK) | SearchResourceEncryptionKey |
Indexes, analyzers, synonym maps
Version 10 | Version 11 equivalent |
---|---|
Index | SearchIndex |
Field | SearchField |
DataType | SearchFieldDataType |
ItemError | SearchIndexerError |
Analyzer | LexicalAnalyzer (also, AnalyzerName to LexicalAnalyzerName ) |
AnalyzeRequest | AnalyzeTextOptions |
StandardAnalyzer | LuceneStandardAnalyzer |
StandardTokenizer | LuceneStandardTokenizer (also, StandardTokenizerV2 to LuceneStandardTokenizerV2 ) |
TokenInfo | AnalyzedTokenInfo |
Tokenizer | LexicalTokenizer (also, TokenizerName to LexicalTokenizerName ) |
SynonymMap.Format | None. Remove references to Format . |
Field definitions are streamlined: SearchableField, SimpleField, ComplexField are new APIs for creating field definitions.
Indexers, datasources, skillsets
Version 10 | Version 11 equivalent |
---|---|
Indexer | SearchIndexer |
DataSource | SearchIndexerDataSourceConnection |
Skill | SearchIndexerSkill |
Skillset | SearchIndexerSkillset |
DataSourceType | SearchIndexerDataSourceType |
Data import
Version 10 | Version 11 equivalent |
---|---|
IndexAction | IndexDocumentsAction |
IndexBatch | IndexDocumentsBatch |
IndexBatchException.FindFailedActionsToRetry() | SearchIndexingBufferedSender |
Query requests and responses
Version 10 | Version 11 equivalent |
---|---|
DocumentsOperationsExtensions.SearchAsync | SearchClient.SearchAsync |
DocumentSearchResult | SearchResult or SearchResults, depending on whether the result is a single document or multiple. |
DocumentSuggestResult | SuggestResults |
SearchParameters | SearchOptions |
SuggestParameters | SuggestOptions |
SearchParameters.Filter | SearchFilter (a new class for constructing OData filter expressions) |
JSON serialization
By default, the Azure SDK uses System.Text.Json for JSON serialization, relying on the capabilities of those APIs to handle text transformations previously implemented through a native SerializePropertyNamesAsCamelCaseAttribute class, which has no counterpart in the new library.
To serialize property names into camelCase, you can use the JsonPropertyNameAttribute (similar to this example).
Alternatively, you can set a JsonNamingPolicy provided in JsonSerializerOptions. The following System.Text.Json code example, taken from the Microsoft.Azure.Core.Spatial readme demonstrates the use of camelCase without having to attribute every property:
// Get the Azure AI Search service endpoint and read-only API key.
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT"));
AzureKeyCredential credential = new AzureKeyCredential(Environment.GetEnvironmentVariable("SEARCH_API_KEY"));
// Create serializer options with our converter to deserialize geographic points.
JsonSerializerOptions serializerOptions = new JsonSerializerOptions
{
Converters =
{
new MicrosoftSpatialGeoJsonConverter()
},
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
SearchClientOptions clientOptions = new SearchClientOptions
{
Serializer = new JsonObjectSerializer(serializerOptions)
};
SearchClient client = new SearchClient(endpoint, "mountains", credential, clientOptions);
Response<SearchResults<Mountain>> results = client.Search<Mountain>("Rainier");
If you're using Newtonsoft.Json for JSON serialization, you can pass in global naming policies using similar attributes, or by using properties on JsonSerializerSettings. For an example equivalent to the previous one, see the Deserializing documents example in the Newtonsoft.Json readme.
Inside v11
Each version of an Azure AI Search client library targets a corresponding version of the REST API. The REST API is considered foundational to the service, with individual SDKs wrapping a version of the REST API. As a .NET developer, it can be helpful to review the more verbose REST API documentation for more in depth coverage of specific objects or operations. Version 11 targets the 2020-06-30 search service specification.
Version 11.0 fully supports the following objects and operations:
- Index creation and management
- Synonym map creation and management
- Indexer creation and management
- Indexer data source creation and management
- Skillset creation and management
- All query types and syntax
Version 11.1 additions (change log details):
- FieldBuilder (added in 11.1)
- Serializer property (added in 11.1) to support custom serialization
Version 11.2 additions (change log details):
EncryptionKey property added indexers, data sources, and skillsets
IndexingParameters.IndexingParametersConfiguration property support
Geospatial types are natively supported in FieldBuilder. SearchFilter can encode geometric types from Microsoft.Spatial without an explicit assembly dependency.
You can also continue to explicitly declare a dependency on Microsoft.Spatial. Examples of this technique are available for System.Text.Json and Newtonsoft.Json.
Version 11.3 additions (change log details):
- KnowledgeStore
- Added support for Azure.Core.GeoJson types in SearchDocument, SearchFilter and FieldBuilder.
- Added EventSource based logging. Event source name is Azure-Search-Documents. Current set of events are focused on tuning batch sizes for SearchIndexingBufferedSender.
- Added CustomEntityLookupSkill and DocumentExtractionSkill. Added DefaultCountryHint in LanguageDetectionSkill.
Before upgrading
Quickstarts, tutorials, and C# samples have been updated to use the Azure.Search.Documents package. We recommend reviewing the samples and walkthroughs to learn about the new APIs before embarking on a migration exercise.
How to use Azure.Search.Documents introduces the most commonly used APIs. Even knowledgeable users of Azure AI Search might want to review this introduction to the new library as a precursor to migration.
Steps to upgrade
The following steps get you started on a code migration by walking through the first set of required tasks, especially regarding client references.
Install the Azure.Search.Documents package by right-clicking on your project references and selecting "Manage NuGet Packages..." in Visual Studio.
Replace using directives for Microsoft.Azure.Search with the following using statements:
using Azure; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Models;
For classes that require JSON serialization, replace
using Newtonsoft.Json
withusing System.Text.Json.Serialization
.Revise client authentication code. In previous versions, you would use properties on the client object to set the API key (for example, the SearchServiceClient.Credentials property). In the current version, use the AzureKeyCredential class to pass the key as a credential, so that if needed, you can update the API key without creating new client objects.
Client properties have been streamlined to just
Endpoint
,ServiceName
, andIndexName
(where appropriate). The following example uses the system Uri class to provide the endpoint and the Environment class to read in the key value:Uri endpoint = new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); AzureKeyCredential credential = new AzureKeyCredential( Environment.GetEnvironmentVariable("SEARCH_API_KEY")); SearchIndexClient indexClient = new SearchIndexClient(endpoint, credential);
Add new client references for indexer-related objects. If you're using indexers, datasources, or skillsets, change the client references to SearchIndexerClient. This client is new in version 11 and has no antecedent.
Revise collections and lists. In the new SDK, all lists are read-only to avoid downstream issues if the list happens to contain null values. The code change is to add items to a list. For example, instead of assigning strings to a Select property, you would add them as follows:
var options = new SearchOptions { SearchMode = SearchMode.All, IncludeTotalCount = true }; // Select fields to return in results. options.Select.Add("HotelName"); options.Select.Add("Description"); options.Select.Add("Tags"); options.Select.Add("Rooms"); options.Select.Add("Rating"); options.Select.Add("LastRenovationDate");
Select, Facets, SearchFields, SourceFields, ScoringParameters, and OrderBy are all lists that now need to be reconstructed.
Update client references for queries and data import. Instances of SearchIndexClient should be changed to SearchClient. To avoid name confusion, make sure you catch all instances before proceeding to the next step.
Update client references for index, synonym map, and analyzer objects. Instances of SearchServiceClient should be changed to SearchIndexClient.
For the remainder of your code, update classes, methods, and properties to use the APIs of the new library. The naming differences section is a place to start but you can also review the change log.
If you have trouble finding equivalent APIs, we suggest logging an issue on https://github.com/MicrosoftDocs/azure-docs/issues so that we can improve the documentation or investigate the problem.
Rebuild the solution. After fixing any build errors or warnings, you can make additional changes to your application to take advantage of new functionality.
Breaking changes
Given the sweeping changes to libraries and APIs, an upgrade to version 11 is non-trivial and constitutes a breaking change in the sense that your code will no longer be backward compatible with version 10 and earlier. For a thorough review of the differences, see the change log for Azure.Search.Documents
.
In terms of service version updates, where code changes in version 11 relate to existing functionality (and not just a refactoring of the APIs), you'll find the following behavior changes:
BM25 ranking algorithm replaces the previous ranking algorithm with newer technology. New services use this algorithm automatically. For existing services, you must set parameters to use the new algorithm.
Ordered results for null values have changed in this version, with null values appearing first if the sort is
asc
and last if the sort isdesc
. If you wrote code to handle how null values are sorted, you should review and potentially remove that code if it's no longer necessary.
Due to these behavior changes, it's likely that there are slight variations in ranked results.