Azure Search Documents Dotnet
MicrosoftOfficialCreated by Microsoft
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Azure.Search.Documents SDK provides a comprehensive set of tools for .NET developers to integrate Azure AI Search into their applications. It supports advanced search paradigms including full-text search, vector search for AI-driven similarity, and semantic ranking for natural language understanding. The SDK is structured around three primary clients: SearchClient for document operations and querying, SearchIndexClient for managing index schemas, and SearchIndexerClient for automating data ingestion and skillsets.
What it does
- Perform full-text, vector, and hybrid search queries
- Manage search indexes, synonym maps, and indexers programmatically
- Execute document CRUD operations including batch updates
- Implement semantic search with captions and answers
- Configure vector search profiles and algorithms
- Support authentication via Microsoft Entra ID or API keys
When to use it
- When building search-enabled .NET applications on Azure
- When implementing RAG (Retrieval-Augmented Generation) pipelines
- When you need to perform semantic or vector-based similarity searches
- When managing search index infrastructure via code
Advantages
- Strongly-typed index definition using FieldBuilder
- Native support for modern search techniques like hybrid and semantic ranking
- Flexible authentication options including managed identity
- Comprehensive batch processing for efficient data ingestion
Usage examples
- “How do I perform a hybrid search using Azure.Search.Documents in C#?”
- The agent provides a code snippet using SearchOptions with both VectorSearchOptions and standard search text to combine keyword and vector retrieval.
- “Show me how to define a search index with a vector field.”
- The agent demonstrates using the FieldBuilder attribute [VectorSearchField] or manual SearchField definition to configure vector dimensions and profiles.
- “How can I enable semantic search for my articles index?”
- The agent provides a configuration example using SemanticSearch and SemanticConfiguration to prioritize fields for semantic ranking.
- “What is the best way to authenticate the SearchClient in production?”
- The agent explains using DefaultAzureCredential with environment variables to leverage managed identities instead of hardcoded API keys.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/microsoft/azure-search-documents-dotnet/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip azure-search-documents-dotnet.zip -d .agents/skills
Documentation by Microsoft
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.IdentityCurrent Versions: Stable v11.7.0, Preview v11.8.0-beta.1
Environment Variables
SEARCH_ENDPOINT=https://<search-service>.search.windows.net # Required: search service endpoint
SEARCH_INDEX_NAME=<index-name> # Required: search index name
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
SEARCH_API_KEY=<api-key> # Only required for AzureKeyCredential authAuthentication
Microsoft Entra Token Credential:
using Azure.Identity;
using Azure.Search.Documents;
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
var credential = new DefaultAzureCredential(
DefaultAzureCredential.DefaultEnvironmentVariableName
);
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#credential-classes
// var credential = new ManagedIdentityCredential();
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
DefaultAzureCredentialover API keys for productionUse
FieldBuilderwith model attributes for type-safe index definitionsUse
CreateOrUpdateIndexAsyncfor idempotent index creationBatch document operations for better throughput
Use
Selectto return only needed fieldsConfigure 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 |
Files
- ATTRIBUTION.mdAdded by AutoGineer998 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md10.1 KiB
- references/semantic-search.md6.8 KiB
- references/vector-search.md5.8 KiB
references/semantic-search.md
Semantic Search Patterns
Detailed patterns for semantic ranking, captions, and answers with Azure.Search.Documents.
Index Configuration for Semantic Search
using Azure.Search.Documents.Indexes.Models;
var index = new SearchIndex("articles")
{
Fields =
{
new SimpleField("id", SearchFieldDataType.String) { IsKey = true },
new SearchableField("title"),
new SearchableField("content"),
new SearchableField("summary"),
new SimpleField("category", SearchFieldDataType.String) { IsFilterable = true }
},
SemanticSearch = new SemanticSearch
{
DefaultConfigurationName = "my-semantic-config",
Configurations =
{
new SemanticConfiguration("my-semantic-config", new SemanticPrioritizedFields
{
TitleField = new SemanticField("title"),
ContentFields =
{
new SemanticField("content"),
new SemanticField("summary")
},
KeywordsFields =
{
new SemanticField("category")
}
})
}
}
};
await indexClient.CreateOrUpdateIndexAsync(index);Basic Semantic Search
using Azure.Search.Documents.Models;
var options = new SearchOptions
{
QueryType = SearchQueryType.Semantic,
SemanticSearch = new SemanticSearchOptions
{
SemanticConfigurationName = "my-semantic-config"
},
Select = { "id", "title", "content" },
Size = 10
};
var results = await searchClient.SearchAsync<Article>(
"What are the best practices for cloud security?",
options);
await foreach (var result in results.Value.GetResultsAsync())
{
Console.WriteLine($"{result.Document.Title} (Score: {result.Score})");
}Semantic Search with Captions
Captions provide highlighted excerpts showing why a document matched:
var options = new SearchOptions
{
QueryType = SearchQueryType.Semantic,
SemanticSearch = new SemanticSearchOptions
{
SemanticConfigurationName = "my-semantic-config",
QueryCaption = new QueryCaption(QueryCaptionType.Extractive)
{
HighlightEnabled = true
}
}
};
var results = await searchClient.SearchAsync<Article>("cloud security best practices", options);
await foreach (var result in results.Value.GetResultsAsync())
{
Console.WriteLine($"Title: {result.Document.Title}");
if (result.SemanticSearch?.Captions != null)
{
foreach (var caption in result.SemanticSearch.Captions)
{
// Highlights contains <em> tags around key phrases
Console.WriteLine($"Caption: {caption.Highlights ?? caption.Text}");
}
}
}Semantic Search with Answers
Answers extract direct responses from the content:
var options = new SearchOptions
{
QueryType = SearchQueryType.Semantic,
SemanticSearch = new SemanticSearchOptions
{
SemanticConfigurationName = "my-semantic-config",
QueryAnswer = new QueryAnswer(QueryAnswerType.Extractive)
{
Count = 3, // Number of answers to return
Threshold = 0.7 // Minimum confidence threshold
},
QueryCaption = new QueryCaption(QueryCaptionType.Extractive)
}
};
var results = await searchClient.SearchAsync<Article>(
"What is zero trust security?",
options);
// Check for semantic answers (appear before documents)
if (results.Value.SemanticSearch?.Answers != null)
{
foreach (var answer in results.Value.SemanticSearch.Answers)
{
Console.WriteLine($"Answer: {answer.Highlights ?? answer.Text}");
Console.WriteLine($"Score: {answer.Score}");
Console.WriteLine($"Document Key: {answer.Key}");
}
}
// Process documents with captions
await foreach (var result in results.Value.GetResultsAsync())
{
Console.WriteLine($"\nDocument: {result.Document.Title}");
Console.WriteLine($"Reranker Score: {result.SemanticSearch?.RerankerScore}");
}Semantic Hybrid Search (Vector + Keyword + Semantic)
Combines all three search modalities for best relevance:
var vectorQuery = new VectorizedQuery(embedding)
{
KNearestNeighborsCount = 50,
Fields = { "contentVector" }
};
var options = new SearchOptions
{
QueryType = SearchQueryType.Semantic,
SemanticSearch = new SemanticSearchOptions
{
SemanticConfigurationName = "my-semantic-config",
QueryCaption = new QueryCaption(QueryCaptionType.Extractive),
QueryAnswer = new QueryAnswer(QueryAnswerType.Extractive)
},
VectorSearch = new VectorSearchOptions
{
Queries = { vectorQuery }
},
Select = { "id", "title", "content" },
Size = 10
};
// Keyword search + vector search + semantic reranking
var results = await searchClient.SearchAsync<Article>(
"best practices for securing cloud infrastructure",
options);Semantic Configuration Options
SemanticPrioritizedFields
| Field | Purpose | Recommendation |
|---|---|---|
TitleField | Document title | Short, descriptive field |
ContentFields | Main content (ordered by priority) | Up to 10 fields, most important first |
KeywordsFields | Keywords/tags | Categorical or tag fields |
QueryCaption Options
new QueryCaption(QueryCaptionType.Extractive)
{
HighlightEnabled = true // Wrap key phrases in <em> tags
}QueryAnswer Options
new QueryAnswer(QueryAnswerType.Extractive)
{
Count = 3, // Max answers to return (1-10)
Threshold = 0.7 // Minimum confidence (0.0-1.0)
}Semantic Ranking Scores
| Score | Description |
|---|---|
result.Score | BM25 keyword relevance score |
result.SemanticSearch.RerankerScore | Semantic relevance (0-4 scale) |
answer.Score | Answer confidence (0-1 scale) |
Error Handling
var results = await searchClient.SearchAsync<Article>(query, options);
// Check if semantic search was applied
if (results.Value.SemanticSearch?.ErrorReason != null)
{
Console.WriteLine($"Semantic search warning: {results.Value.SemanticSearch.ErrorReason}");
// Results still returned, but without semantic ranking
}Best Practices
Configure semantic fields carefully - Title and content fields significantly impact quality
Use answers for Q&A scenarios - Set appropriate threshold to filter low-confidence answers
Combine with vector search - Semantic hybrid provides best relevance
Monitor reranker scores - Scores below 1.0 indicate weak semantic match
Enable captions - Helps users understand why documents matched
Set answer count appropriately - More answers = more latency
Use filters before semantic ranking - Reduces documents to rerank
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an API key
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-sdk-dotnet/skills/azure-search-documents-dotnet · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-search-documents-dotnet.zip