|
Add this skill
npx mdskills install sickn33/azure-search-documents-dotnetComprehensive Azure Search SDK reference with excellent code examples and clear authentication patterns
1---2name: azure-search-documents-dotnet3description: |4 Azure AI Search SDK for .NET (Azure.Search.Documents). Use for building search applications with full-text, vector, semantic, and hybrid search. Covers SearchClient (queries, document CRUD), SearchIndexClient (index management), and SearchIndexerClient (indexers, skillsets). Triggers: "Azure Search .NET", "SearchClient", "SearchIndexClient", "vector search C#", "semantic search .NET", "hybrid search", "Azure.Search.Documents".5package: Azure.Search.Documents6---78# Azure.Search.Documents (.NET)910Build search applications with full-text, vector, semantic, and hybrid search capabilities.1112## Installation1314```bash15dotnet add package Azure.Search.Documents16dotnet add package Azure.Identity17```1819**Current Versions**: Stable v11.7.0, Preview v11.8.0-beta.12021## Environment Variables2223```bash24SEARCH_ENDPOINT=https://<search-service>.search.windows.net25SEARCH_INDEX_NAME=<index-name>26# For API key auth (not recommended for production)27SEARCH_API_KEY=<api-key>28```2930## Authentication3132**DefaultAzureCredential (preferred)**:33```csharp34using Azure.Identity;35using Azure.Search.Documents;3637var credential = new DefaultAzureCredential();38var client = new SearchClient(39 new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")),40 Environment.GetEnvironmentVariable("SEARCH_INDEX_NAME"),41 credential);42```4344**API Key**:45```csharp46using Azure;47using Azure.Search.Documents;4849var credential = new AzureKeyCredential(50 Environment.GetEnvironmentVariable("SEARCH_API_KEY"));51var client = new SearchClient(52 new Uri(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")),53 Environment.GetEnvironmentVariable("SEARCH_INDEX_NAME"),54 credential);55```5657## Client Selection5859| Client | Purpose |60|--------|---------|61| `SearchClient` | Query indexes, upload/update/delete documents |62| `SearchIndexClient` | Create/manage indexes, synonym maps |63| `SearchIndexerClient` | Manage indexers, skillsets, data sources |6465## Index Creation6667### Using FieldBuilder (Recommended)6869```csharp70using Azure.Search.Documents.Indexes;71using Azure.Search.Documents.Indexes.Models;7273// Define model with attributes74public class Hotel75{76 [SimpleField(IsKey = true, IsFilterable = true)]77 public string HotelId { get; set; }7879 [SearchableField(IsSortable = true)]80 public string HotelName { get; set; }8182 [SearchableField(AnalyzerName = LexicalAnalyzerName.EnLucene)]83 public string Description { get; set; }8485 [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]86 public double? Rating { get; set; }8788 [VectorSearchField(VectorSearchDimensions = 1536, VectorSearchProfileName = "vector-profile")]89 public ReadOnlyMemory<float>? DescriptionVector { get; set; }90}9192// Create index93var indexClient = new SearchIndexClient(endpoint, credential);94var fieldBuilder = new FieldBuilder();95var fields = fieldBuilder.Build(typeof(Hotel));9697var index = new SearchIndex("hotels")98{99 Fields = fields,100 VectorSearch = new VectorSearch101 {102 Profiles = { new VectorSearchProfile("vector-profile", "hnsw-algo") },103 Algorithms = { new HnswAlgorithmConfiguration("hnsw-algo") }104 }105};106107await indexClient.CreateOrUpdateIndexAsync(index);108```109110### Manual Field Definition111112```csharp113var index = new SearchIndex("hotels")114{115 Fields =116 {117 new SimpleField("hotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true },118 new SearchableField("hotelName") { IsSortable = true },119 new SearchableField("description") { AnalyzerName = LexicalAnalyzerName.EnLucene },120 new SimpleField("rating", SearchFieldDataType.Double) { IsFilterable = true, IsSortable = true },121 new SearchField("descriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single))122 {123 VectorSearchDimensions = 1536,124 VectorSearchProfileName = "vector-profile"125 }126 }127};128```129130## Document Operations131132```csharp133var searchClient = new SearchClient(endpoint, indexName, credential);134135// Upload (add new)136var hotels = new[] { new Hotel { HotelId = "1", HotelName = "Hotel A" } };137await searchClient.UploadDocumentsAsync(hotels);138139// Merge (update existing)140await searchClient.MergeDocumentsAsync(hotels);141142// Merge or Upload (upsert)143await searchClient.MergeOrUploadDocumentsAsync(hotels);144145// Delete146await searchClient.DeleteDocumentsAsync("hotelId", new[] { "1", "2" });147148// Batch operations149var batch = IndexDocumentsBatch.Create(150 IndexDocumentsAction.Upload(hotel1),151 IndexDocumentsAction.Merge(hotel2),152 IndexDocumentsAction.Delete(hotel3));153await searchClient.IndexDocumentsAsync(batch);154```155156## Search Patterns157158### Basic Search159160```csharp161var options = new SearchOptions162{163 Filter = "rating ge 4",164 OrderBy = { "rating desc" },165 Select = { "hotelId", "hotelName", "rating" },166 Size = 10,167 Skip = 0,168 IncludeTotalCount = true169};170171SearchResults<Hotel> results = await searchClient.SearchAsync<Hotel>("luxury", options);172173Console.WriteLine($"Total: {results.TotalCount}");174await foreach (SearchResult<Hotel> result in results.GetResultsAsync())175{176 Console.WriteLine($"{result.Document.HotelName} (Score: {result.Score})");177}178```179180### Faceted Search181182```csharp183var options = new SearchOptions184{185 Facets = { "rating,count:5", "category" }186};187188var results = await searchClient.SearchAsync<Hotel>("*", options);189190foreach (var facet in results.Value.Facets["rating"])191{192 Console.WriteLine($"Rating {facet.Value}: {facet.Count}");193}194```195196### Autocomplete and Suggestions197198```csharp199// Autocomplete200var autocompleteOptions = new AutocompleteOptions { Mode = AutocompleteMode.OneTermWithContext };201var autocomplete = await searchClient.AutocompleteAsync("lux", "suggester-name", autocompleteOptions);202203// Suggestions204var suggestOptions = new SuggestOptions { UseFuzzyMatching = true };205var suggestions = await searchClient.SuggestAsync<Hotel>("lux", "suggester-name", suggestOptions);206```207208## Vector Search209210See [references/vector-search.md](references/vector-search.md) for detailed patterns.211212```csharp213using Azure.Search.Documents.Models;214215// Pure vector search216var vectorQuery = new VectorizedQuery(embedding)217{218 KNearestNeighborsCount = 5,219 Fields = { "descriptionVector" }220};221222var options = new SearchOptions223{224 VectorSearch = new VectorSearchOptions225 {226 Queries = { vectorQuery }227 }228};229230var results = await searchClient.SearchAsync<Hotel>(null, options);231```232233## Semantic Search234235See [references/semantic-search.md](references/semantic-search.md) for detailed patterns.236237```csharp238var options = new SearchOptions239{240 QueryType = SearchQueryType.Semantic,241 SemanticSearch = new SemanticSearchOptions242 {243 SemanticConfigurationName = "my-semantic-config",244 QueryCaption = new QueryCaption(QueryCaptionType.Extractive),245 QueryAnswer = new QueryAnswer(QueryAnswerType.Extractive)246 }247};248249var results = await searchClient.SearchAsync<Hotel>("best hotel for families", options);250251// Access semantic answers252foreach (var answer in results.Value.SemanticSearch.Answers)253{254 Console.WriteLine($"Answer: {answer.Text} (Score: {answer.Score})");255}256257// Access captions258await foreach (var result in results.Value.GetResultsAsync())259{260 var caption = result.SemanticSearch?.Captions?.FirstOrDefault();261 Console.WriteLine($"Caption: {caption?.Text}");262}263```264265## Hybrid Search (Vector + Keyword + Semantic)266267```csharp268var vectorQuery = new VectorizedQuery(embedding)269{270 KNearestNeighborsCount = 5,271 Fields = { "descriptionVector" }272};273274var options = new SearchOptions275{276 QueryType = SearchQueryType.Semantic,277 SemanticSearch = new SemanticSearchOptions278 {279 SemanticConfigurationName = "my-semantic-config"280 },281 VectorSearch = new VectorSearchOptions282 {283 Queries = { vectorQuery }284 }285};286287// Combines keyword search, vector search, and semantic ranking288var results = await searchClient.SearchAsync<Hotel>("luxury beachfront", options);289```290291## Field Attributes Reference292293| Attribute | Purpose |294|-----------|---------|295| `SimpleField` | Non-searchable field (filters, sorting, facets) |296| `SearchableField` | Full-text searchable field |297| `VectorSearchField` | Vector embedding field |298| `IsKey = true` | Document key (required, one per index) |299| `IsFilterable = true` | Enable $filter expressions |300| `IsSortable = true` | Enable $orderby |301| `IsFacetable = true` | Enable faceted navigation |302| `IsHidden = true` | Exclude from results |303| `AnalyzerName` | Specify text analyzer |304305## Error Handling306307```csharp308using Azure;309310try311{312 var results = await searchClient.SearchAsync<Hotel>("query");313}314catch (RequestFailedException ex) when (ex.Status == 404)315{316 Console.WriteLine("Index not found");317}318catch (RequestFailedException ex)319{320 Console.WriteLine($"Search error: {ex.Status} - {ex.ErrorCode}: {ex.Message}");321}322```323324## Best Practices3253261. **Use `DefaultAzureCredential`** over API keys for production3272. **Use `FieldBuilder`** with model attributes for type-safe index definitions3283. **Use `CreateOrUpdateIndexAsync`** for idempotent index creation3294. **Batch document operations** for better throughput3305. **Use `Select`** to return only needed fields3316. **Configure semantic search** for natural language queries3327. **Combine vector + keyword + semantic** for best relevance333334## Reference Files335336| File | Contents |337|------|----------|338| [references/vector-search.md](references/vector-search.md) | Vector search, hybrid search, vectorizers |339| [references/semantic-search.md](references/semantic-search.md) | Semantic ranking, captions, answers |340
Full transparency — inspect the skill content before installing.