- Azure.Search.Documents (.NET)
- Build search applications with full-text, vector, semantic, and hybrid search capabilities.
- Installation
- dotnet
- add
- package Azure.Search.Documents
- dotnet
- add
- package Azure.Identity
- Current Versions
- Stable v11.7.0, Preview v11.8.0-beta.1
Environment Variables
SEARCH_ENDPOINT
=
https://
<
search-service
.search.windows.net SEARCH_INDEX_NAME = < index-name
For API key auth (not recommended for production)
SEARCH_API_KEY
< api-key
Authentication DefaultAzureCredential (preferred) : using Azure . Identity ; using Azure . Search . Documents ; var credential = new DefaultAzureCredential ( ) ; var client = new SearchClient ( new Uri ( Environment . GetEnvironmentVariable ( "SEARCH_ENDPOINT" ) ) , Environment . GetEnvironmentVariable ( "SEARCH_INDEX_NAME" ) , credential ) ; API Key : using Azure ; using Azure . Search . Documents ; var credential = new AzureKeyCredential ( Environment . GetEnvironmentVariable ( "SEARCH_API_KEY" ) ) ; var client = new SearchClient ( new Uri ( Environment . GetEnvironmentVariable ( "SEARCH_ENDPOINT" ) ) , Environment . GetEnvironmentVariable ( "SEARCH_INDEX_NAME" ) , credential ) ; Client Selection Client Purpose SearchClient Query indexes, upload/update/delete documents SearchIndexClient Create/manage indexes, synonym maps SearchIndexerClient Manage indexers, skillsets, data sources Index Creation Using FieldBuilder (Recommended) using Azure . Search . Documents . Indexes ; using Azure . Search . Documents . Indexes . Models ; // Define model with attributes public class Hotel { [ SimpleField ( IsKey = true , IsFilterable = true ) ] public string HotelId { get ; set ; } [ SearchableField ( IsSortable = true ) ] public string HotelName { get ; set ; } [ SearchableField ( AnalyzerName = LexicalAnalyzerName . EnLucene ) ] public string Description { get ; set ; } [ SimpleField ( IsFilterable = true , IsSortable = true , IsFacetable = true ) ] public double ? Rating { get ; set ; } [ VectorSearchField ( VectorSearchDimensions = 1536 , VectorSearchProfileName = "vector-profile" ) ] public ReadOnlyMemory < float
? DescriptionVector { get ; set ; } } // Create index var indexClient = new SearchIndexClient ( endpoint , credential ) ; var fieldBuilder = new FieldBuilder ( ) ; var fields = fieldBuilder . Build ( typeof ( Hotel ) ) ; var index = new SearchIndex ( "hotels" ) { Fields = fields , VectorSearch = new VectorSearch { Profiles = { new VectorSearchProfile ( "vector-profile" , "hnsw-algo" ) } , Algorithms = { new HnswAlgorithmConfiguration ( "hnsw-algo" ) } } } ; await indexClient . CreateOrUpdateIndexAsync ( index ) ; Manual Field Definition var index = new SearchIndex ( "hotels" ) { Fields = { new SimpleField ( "hotelId" , SearchFieldDataType . String ) { IsKey = true , IsFilterable = true } , new SearchableField ( "hotelName" ) { IsSortable = true } , new SearchableField ( "description" ) { AnalyzerName = LexicalAnalyzerName . EnLucene } , new SimpleField ( "rating" , SearchFieldDataType . Double ) { IsFilterable = true , IsSortable = true } , new SearchField ( "descriptionVector" , SearchFieldDataType . Collection ( SearchFieldDataType . Single ) ) { VectorSearchDimensions = 1536 , VectorSearchProfileName = "vector-profile" } } } ; Document Operations var searchClient = new SearchClient ( endpoint , indexName , credential ) ; // Upload (add new) var hotels = new [ ] { new Hotel { HotelId = "1" , HotelName = "Hotel A" } } ; await searchClient . UploadDocumentsAsync ( hotels ) ; // Merge (update existing) await searchClient . MergeDocumentsAsync ( hotels ) ; // Merge or Upload (upsert) await searchClient . MergeOrUploadDocumentsAsync ( hotels ) ; // Delete await searchClient . DeleteDocumentsAsync ( "hotelId" , new [ ] { "1" , "2" } ) ; // Batch operations var batch = IndexDocumentsBatch . Create ( IndexDocumentsAction . Upload ( hotel1 ) , IndexDocumentsAction . Merge ( hotel2 ) , IndexDocumentsAction . Delete ( hotel3 ) ) ; await searchClient . IndexDocumentsAsync ( batch ) ; Search Patterns Basic Search var options = new SearchOptions { Filter = "rating ge 4" , OrderBy = { "rating desc" } , Select = { "hotelId" , "hotelName" , "rating" } , Size = 10 , Skip = 0 , IncludeTotalCount = true } ; SearchResults < Hotel
results
await searchClient . SearchAsync < Hotel
( "luxury" , options ) ; Console . WriteLine ( $"Total: { results . TotalCount } " ) ; await foreach ( SearchResult < Hotel
result in results . GetResultsAsync ( ) ) { Console . WriteLine ( $" { result . Document . HotelName } (Score: { result . Score } )" ) ; } Faceted Search var options = new SearchOptions { Facets = { "rating,count:5" , "category" } } ; var results = await searchClient . SearchAsync < Hotel
( "*" , options ) ; foreach ( var facet in results . Value . Facets [ "rating" ] ) { Console . WriteLine ( $"Rating { facet . Value } : { facet . Count } " ) ; } Autocomplete and Suggestions // Autocomplete var autocompleteOptions = new AutocompleteOptions { Mode = AutocompleteMode . OneTermWithContext } ; var autocomplete = await searchClient . AutocompleteAsync ( "lux" , "suggester-name" , autocompleteOptions ) ; // Suggestions var suggestOptions = new SuggestOptions { UseFuzzyMatching = true } ; var suggestions = await searchClient . SuggestAsync < Hotel
( "lux" , "suggester-name" , suggestOptions ) ; Vector Search See references/vector-search.md for detailed patterns. using Azure . Search . Documents . Models ; // Pure vector search var vectorQuery = new VectorizedQuery ( embedding ) { KNearestNeighborsCount = 5 , Fields = { "descriptionVector" } } ; var options = new SearchOptions { VectorSearch = new VectorSearchOptions { Queries = { vectorQuery } } } ; var results = await searchClient . SearchAsync < Hotel
( null , options ) ; Semantic Search See references/semantic-search.md for detailed patterns. var options = new SearchOptions { QueryType = SearchQueryType . Semantic , SemanticSearch = new SemanticSearchOptions { SemanticConfigurationName = "my-semantic-config" , QueryCaption = new QueryCaption ( QueryCaptionType . Extractive ) , QueryAnswer = new QueryAnswer ( QueryAnswerType . Extractive ) } } ; var results = await searchClient . SearchAsync < Hotel
( "best hotel for families" , options ) ; // Access semantic answers foreach ( var answer in results . Value . SemanticSearch . Answers ) { Console . WriteLine ( $"Answer: { answer . Text } (Score: { answer . Score } )" ) ; } // Access captions await foreach ( var result in results . Value . GetResultsAsync ( ) ) { var caption = result . SemanticSearch ?. Captions ?. FirstOrDefault ( ) ; Console . WriteLine ( $"Caption: { caption ?. Text } " ) ; } Hybrid Search (Vector + Keyword + Semantic) var vectorQuery = new VectorizedQuery ( embedding ) { KNearestNeighborsCount = 5 , Fields = { "descriptionVector" } } ; var options = new SearchOptions { QueryType = SearchQueryType . Semantic , SemanticSearch = new SemanticSearchOptions { SemanticConfigurationName = "my-semantic-config" } , VectorSearch = new VectorSearchOptions { Queries = { vectorQuery } } } ; // Combines keyword search, vector search, and semantic ranking var results = await searchClient . SearchAsync < Hotel
( "luxury beachfront" , options ) ; Field Attributes Reference Attribute Purpose SimpleField Non-searchable field (filters, sorting, facets) SearchableField Full-text searchable field VectorSearchField Vector embedding field IsKey = true Document key (required, one per index) IsFilterable = true Enable $filter expressions IsSortable = true Enable $orderby IsFacetable = true Enable faceted navigation IsHidden = true Exclude from results AnalyzerName Specify text analyzer Error Handling using Azure ; try { var results = await searchClient . SearchAsync < Hotel
( "query" ) ; } catch ( RequestFailedException ex ) when ( ex . Status == 404 ) { Console . WriteLine ( "Index not found" ) ; } catch ( RequestFailedException ex ) { Console . WriteLine ( $"Search error: { ex . Status } - { ex . ErrorCode } : { ex . Message } " ) ; } Best Practices Use DefaultAzureCredential over API keys for production Use FieldBuilder with model attributes for type-safe index definitions Use CreateOrUpdateIndexAsync for idempotent index creation Batch document operations for better throughput Use Select to return only needed fields Configure semantic search for natural language queries Combine vector + keyword + semantic for best relevance Reference Files File Contents references/vector-search.md Vector search, hybrid search, vectorizers references/semantic-search.md Semantic ranking, captions, answers When to Use This skill is applicable to execute the workflow or actions described in the overview.