Azure Search Documents TS
MicrosoftOfficialCreated by Microsoft
- Skill
- Tool integration
- Data and AI
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The azure-search-documents-ts skill provides a comprehensive guide to using the @azure/search-documents SDK for JavaScript and TypeScript. It covers the full lifecycle of search application development, including index creation, document management, and advanced retrieval techniques. Developers can implement full-text search, vector search, hybrid search, and semantic ranking to build robust, AI-powered search experiences. The skill also details how to handle authentication using Azure Identity, manage index schemas, and perform batch operations for efficient data ingestion.
What it does
- Create and manage search indexes with custom field definitions.
- Implement vector search using pre-computed embeddings or integrated vectorization.
- Execute hybrid search queries combining keyword and vector retrieval.
- Enable semantic ranking for improved relevance in natural language queries.
- Perform batch operations for uploading, merging, or deleting documents.
- Configure autocomplete and suggestion features for search interfaces.
When to use it
- When building search-enabled applications on the Azure platform.
- When implementing RAG (Retrieval-Augmented Generation) pipelines with knowledge bases.
- When you need to support complex search requirements like semantic reranking or vector-based similarity.
- When managing search index schemas programmatically in a TypeScript environment.
Advantages
- Native support for modern search paradigms like vector and hybrid search.
- Strongly-typed TypeScript interfaces for index and search configurations.
- Seamless integration with Azure Identity for secure authentication.
- Built-in support for semantic ranking to enhance search result quality.
Usage examples
- “How do I create a search index with a vector field using the Azure SDK?”
- The agent provides a code snippet demonstrating the use of SearchIndexClient to define an index with vectorSearch profiles and vectorSearchDimensions.
- “Show me how to perform a hybrid search with text and vector queries.”
- The agent provides an example using the search method with both a search string and vectorSearchOptions to combine keyword and vector results.
- “How can I enable semantic ranking for my search results?”
- The agent explains how to configure semanticSearch in the index and use queryType: 'semantic' in the search options.
- “How do I upload multiple documents to my index in one go?”
- The agent demonstrates the use of the indexDocuments method with an array of actions to perform batch uploads, merges, or deletions.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/microsoft/azure-search-documents-ts/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip azure-search-documents-ts.zip -d .agents/skills
Documentation by Microsoft
Azure AI Search SDK for TypeScript
Build search applications with vector, hybrid, and semantic search capabilities.
Installation
npm install @azure/search-documents @azure/identityEnvironment Variables
AZURE_SEARCH_ENDPOINT=https://<service-name>.search.windows.net
AZURE_SEARCH_INDEX_NAME=my-index
AZURE_SEARCH_ADMIN_KEY=<admin-key> # Optional if using Entra ID
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in productionAuthentication
import { SearchClient, SearchIndexClient } from "@azure/search-documents";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
const endpoint = process.env.AZURE_SEARCH_ENDPOINT!;
const indexName = process.env.AZURE_SEARCH_INDEX_NAME!;
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
// For searching
const searchClient = new SearchClient(endpoint, indexName, credential);
// For index management
const indexClient = new SearchIndexClient(endpoint, credential);Core Workflow
Create Index with Vector Field
import { SearchIndex, SearchField, VectorSearch } from "@azure/search-documents";
const index: SearchIndex = {
name: "products",
fields: [
{ name: "id", type: "Edm.String", key: true },
{ name: "title", type: "Edm.String", searchable: true },
{ name: "description", type: "Edm.String", searchable: true },
{ name: "category", type: "Edm.String", filterable: true, facetable: true },
{
name: "embedding",
type: "Collection(Edm.Single)",
searchable: true,
vectorSearchDimensions: 1536,
vectorSearchProfileName: "vector-profile",
},
],
vectorSearch: {
algorithms: [
{ name: "hnsw-algorithm", kind: "hnsw" },
],
profiles: [
{ name: "vector-profile", algorithmConfigurationName: "hnsw-algorithm" },
],
},
};
await indexClient.createOrUpdateIndex(index);Index Documents
const documents = [
{ id: "1", title: "Widget", description: "A useful widget", category: "Tools", embedding: [...] },
{ id: "2", title: "Gadget", description: "A cool gadget", category: "Electronics", embedding: [...] },
];
const result = await searchClient.uploadDocuments(documents);
console.log(`Indexed ${result.results.length} documents`);Full-Text Search
const results = await searchClient.search("widget", {
select: ["id", "title", "description"],
filter: "category eq 'Tools'",
orderBy: ["title asc"],
top: 10,
});
for await (const result of results.results) {
console.log(`${result.document.title}: ${result.score}`);
}Vector Search
const queryVector = await getEmbedding("useful tool"); // Your embedding function
const results = await searchClient.search("*", {
vectorSearchOptions: {
queries: [
{
kind: "vector",
vector: queryVector,
fields: ["embedding"],
kNearestNeighborsCount: 10,
},
],
},
select: ["id", "title", "description"],
});
for await (const result of results.results) {
console.log(`${result.document.title}: ${result.score}`);
}Hybrid Search (Text + Vector)
const queryVector = await getEmbedding("useful tool");
const results = await searchClient.search("tool", {
vectorSearchOptions: {
queries: [
{
kind: "vector",
vector: queryVector,
fields: ["embedding"],
kNearestNeighborsCount: 50,
},
],
},
select: ["id", "title", "description"],
top: 10,
});Semantic Search
// Index must have semantic configuration
const index: SearchIndex = {
name: "products",
fields: [...],
semanticSearch: {
configurations: [
{
name: "semantic-config",
prioritizedFields: {
titleField: { name: "title" },
contentFields: [{ name: "description" }],
},
},
],
},
};
// Search with semantic ranking
const results = await searchClient.search("best tool for the job", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "semantic-config",
captions: { captionType: "extractive" },
answers: { answerType: "extractive", count: 3 },
},
select: ["id", "title", "description"],
});
for await (const result of results.results) {
console.log(`${result.document.title}`);
console.log(` Caption: ${result.captions?.[0]?.text}`);
console.log(` Reranker Score: ${result.rerankerScore}`);
}Filtering and Facets
// Filter syntax
const results = await searchClient.search("*", {
filter: "category eq 'Electronics' and price lt 100",
facets: ["category,count:10", "brand"],
});
// Access facets
for (const [facetName, facetResults] of Object.entries(results.facets || {})) {
console.log(`${facetName}:`);
for (const facet of facetResults) {
console.log(` ${facet.value}: ${facet.count}`);
}
}Autocomplete and Suggestions
// Create suggester in index
const index: SearchIndex = {
name: "products",
fields: [...],
suggesters: [
{ name: "sg", sourceFields: ["title", "description"] },
],
};
// Autocomplete
const autocomplete = await searchClient.autocomplete("wid", "sg", {
mode: "twoTerms",
top: 5,
});
// Suggestions
const suggestions = await searchClient.suggest("wid", "sg", {
select: ["title"],
top: 5,
});Batch Operations
// Batch upload, merge, delete
const batch = [
{ upload: { id: "1", title: "New Item" } },
{ merge: { id: "2", title: "Updated Title" } },
{ delete: { id: "3" } },
];
const result = await searchClient.indexDocuments({ actions: batch });Key Types
import {
SearchClient,
SearchIndexClient,
SearchIndexerClient,
SearchIndex,
SearchField,
SearchOptions,
VectorSearch,
SemanticSearch,
SearchIterator,
} from "@azure/search-documents";Best Practices
Use hybrid search - Combine vector + text for best results
Enable semantic ranking - Improves relevance for natural language queries
Batch document uploads - Use
uploadDocumentswith arrays, not single docsUse filters for security - Implement document-level security with filters
Index incrementally - Use
mergeOrUploadDocumentsfor updatesMonitor query performance - Use
includeTotalCount: truesparingly in production
Files
- ATTRIBUTION.mdAdded by AutoGineer994 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md7.1 KiB
- references/semantic-ranking.md11.1 KiB
- references/vector-search.md9.8 KiB
references/semantic-ranking.md
@azure/search-documents - Semantic Ranking Patterns
Reference documentation for semantic search and ranking in the Azure AI Search TypeScript SDK.
Source: Azure SDK for JS - search-documents
Installation
npm install @azure/search-documents @azure/identitySemanticSearchOptions Interface
interface SemanticSearchOptions {
/** Name of the semantic configuration to use */
configurationName?: string;
/** Error handling mode: "partial" or "fail" */
errorMode?: SemanticErrorMode;
/** Max wait time for semantic processing (ms) */
maxWaitInMilliseconds?: number;
/** Extract answers from documents */
answers?: QueryAnswer;
/** Extract captions with highlighting */
captions?: QueryCaption;
/** AI-generated query rewrites */
queryRewrites?: QueryRewrites;
/** Separate query for semantic reranking */
semanticQuery?: string;
/** Fields for semantic search */
semanticFields?: string[];
/** Enable debug info */
debugMode?: QueryDebugMode;
}Basic Semantic Search
Enable semantic ranking with queryType: "semantic":
import { SearchClient } from "@azure/search-documents";
import { DefaultAzureCredential } from "@azure/identity";
interface Article {
id: string;
title: string;
content: string;
category: string;
}
const client = new SearchClient<Article>(
process.env["AZURE_SEARCH_ENDPOINT"]!,
"articles",
new DefaultAzureCredential()
);
const results = await client.search("what causes climate change", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "my-semantic-config",
},
select: ["id", "title", "content"],
top: 10,
});
for await (const result of results.results) {
console.log(`${result.document.title}`);
console.log(`Reranker Score: ${result.rerankerScore}`);
}Extractive Captions
Extract representative passages with keyword highlighting:
const results = await client.search("renewable energy benefits", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "my-semantic-config",
captions: {
captionType: "extractive",
highlight: true,
},
},
});
for await (const result of results.results) {
console.log(`Title: ${result.document.title}`);
// Access captions
result.captions?.forEach((caption) => {
console.log(`Caption: ${caption.text}`);
console.log(`Highlighted: ${caption.highlights}`); // With <em> tags
});
}Caption Options
interface QueryCaption {
/** Caption type: "extractive" | "none" */
captionType: QueryCaptionType;
/** Include highlighting with <em> tags */
highlight?: boolean;
}Extractive Answers
Extract direct answers for Q&A-style queries:
const results = await client.search("what is the speed of light", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "science-config",
answers: {
answerType: "extractive",
count: 3, // Number of answers to extract
threshold: 0.7, // Minimum confidence threshold
},
},
});
// Access answers at the result set level
if (results.answers && results.answers.length > 0) {
console.log("Top Answers:");
results.answers.forEach((answer, i) => {
console.log(`${i + 1}. ${answer.text}`);
console.log(` Highlights: ${answer.highlights}`);
console.log(` Score: ${answer.score}`);
console.log(` Document: ${answer.key}`);
});
}Answer Options
interface QueryAnswer {
/** Answer type: "extractive" | "none" */
answerType: QueryAnswerType;
/** Number of answers to return (1-10) */
count?: number;
/** Minimum confidence threshold (0-1) */
threshold?: number;
}Query Rewrites
Enable AI-generated query rewrites for better recall:
const results = await client.search("ML algorithms", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "tech-config",
queryRewrites: {
rewritesType: "generative",
count: 3, // Number of rewrites to generate
},
},
});
// Access generated rewrites
if (results.queryRewrites && results.queryRewrites.length > 0) {
console.log("Query Rewrites:");
results.queryRewrites.forEach((rewrite) => {
console.log(`- ${rewrite}`);
});
}Semantic + Hybrid Search
Combine semantic ranking with vector search for best results:
const results = await client.search("climate change solutions", {
// Enable semantic reranking
queryType: "semantic",
semanticSearchOptions: {
configurationName: "articles-semantic",
captions: { captionType: "extractive", highlight: true },
answers: { answerType: "extractive", count: 3 },
},
// Add vector search
vectorSearchOptions: {
queries: [
{
kind: "text",
text: "climate change solutions",
kNearestNeighborsCount: 50,
fields: ["contentVector"],
},
],
},
// Keyword search fields
searchFields: ["title", "content"],
top: 10,
select: ["id", "title", "content", "category"],
});
// Results are:
// 1. Retrieved via hybrid (keyword + vector)
// 2. Reranked by semantic model
// 3. Enriched with captions and answersSemantic Query Override
Use different queries for retrieval vs. semantic reranking:
const results = await client.search("ML", {
// "ML" used for keyword matching
queryType: "semantic",
semanticSearchOptions: {
configurationName: "tech-config",
// Full question used for semantic reranking
semanticQuery: "What are the best machine learning algorithms for classification?",
captions: { captionType: "extractive" },
},
});Debug Mode
Get detailed information about semantic processing:
const results = await client.search("quantum computing applications", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "science-config",
debugMode: "semantic", // "disabled" | "speller" | "semantic" | "all"
},
});
for await (const result of results.results) {
// Access debug info per document
console.log(`Document: ${result.document.title}`);
console.log(`Debug Info:`, result.documentDebugInfo);
}Error Handling
Control behavior when semantic processing fails:
const results = await client.search("complex query here", {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "my-config",
// "partial" - Return results without semantic enrichment on failure
// "fail" - Return error if semantic processing fails
errorMode: "partial",
// Timeout for semantic processing
maxWaitInMilliseconds: 5000,
},
});Index Semantic Configuration
Define semantic configuration in your index:
import { SearchIndexClient, SearchIndex } from "@azure/search-documents";
const indexClient = new SearchIndexClient(endpoint, credential);
const index: SearchIndex = {
name: "articles",
fields: [
{ name: "id", type: "Edm.String", key: true },
{ name: "title", type: "Edm.String", searchable: true },
{ name: "content", type: "Edm.String", searchable: true },
{ name: "summary", type: "Edm.String", searchable: true },
{ name: "category", type: "Edm.String", filterable: true },
],
semanticSearch: {
configurations: [
{
name: "articles-semantic",
prioritizedFields: {
// Title field (highest priority for reranking)
titleField: {
fieldName: "title",
},
// Content fields (used for caption/answer extraction)
contentFields: [
{ fieldName: "content" },
{ fieldName: "summary" },
],
// Keyword fields (boost exact matches)
keywordsFields: [
{ fieldName: "category" },
],
},
},
],
defaultConfiguration: "articles-semantic",
},
};
await indexClient.createOrUpdateIndex(index);Complete Example
import { SearchClient } from "@azure/search-documents";
import { DefaultAzureCredential } from "@azure/identity";
interface Document {
id: string;
title: string;
content: string;
contentVector: number[];
category: string;
}
async function semanticHybridSearch(query: string) {
const client = new SearchClient<Document>(
process.env["AZURE_SEARCH_ENDPOINT"]!,
"knowledge-base",
new DefaultAzureCredential()
);
const results = await client.search(query, {
queryType: "semantic",
semanticSearchOptions: {
configurationName: "default-semantic",
captions: { captionType: "extractive", highlight: true },
answers: { answerType: "extractive", count: 3, threshold: 0.7 },
},
vectorSearchOptions: {
queries: [
{
kind: "text",
text: query,
kNearestNeighborsCount: 50,
fields: ["contentVector"],
},
],
},
searchFields: ["title", "content"],
top: 10,
select: ["id", "title", "content", "category"],
});
// Process answers first (highest quality extracts)
const response: {
answers: Array<{ text: string; score: number; documentId: string }>;
results: Array<{
document: Document;
score: number;
rerankerScore: number;
captions: string[];
}>;
} = {
answers: [],
results: [],
};
// Extract answers
if (results.answers) {
response.answers = results.answers.map((a) => ({
text: a.highlights || a.text || "",
score: a.score ?? 0,
documentId: a.key || "",
}));
}
// Extract results with captions
for await (const result of results.results) {
response.results.push({
document: result.document,
score: result.score ?? 0,
rerankerScore: result.rerankerScore ?? 0,
captions: result.captions?.map((c) => c.highlights || c.text || "") ?? [],
});
}
return response;
}
// Usage
const response = await semanticHybridSearch("how does photosynthesis work");
console.log("=== Direct Answers ===");
response.answers.forEach((a, i) => {
console.log(`${i + 1}. ${a.text} (score: ${a.score})`);
});
console.log("\n=== Search Results ===");
response.results.forEach((r, i) => {
console.log(`${i + 1}. ${r.document.title}`);
console.log(` Reranker Score: ${r.rerankerScore}`);
console.log(` Caption: ${r.captions[0] || "N/A"}`);
});Best Practices
Use extractive answers - For Q&A scenarios, answers provide direct responses
Enable captions - They provide relevant snippets without returning full content
Combine with hybrid search - Semantic + vector + keyword yields best results
Set appropriate thresholds - Filter low-confidence answers
Configure semantic fields - Prioritize title > content > keywords
Use partial error mode - Gracefully degrade when semantic processing fails
Monitor latency - Semantic processing adds ~100-300ms latency
See Also
Vector Search Patterns - Combine with vector search
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 Node.js
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-typescript/skills/azure-search-documents-ts · 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 or Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-search-documents-ts.zip