Azure Cognitive Search is a search-as-a-service cloud solution that gives developers APIs and tools for adding a rich search experience over private, heterogeneous content in web, mobile, and enterprise applications.
Azure Cognitive Search is well suited for the following application scenarios:
Use the client library to:
Source code | Package (NPM) | API reference documentation | Product documentation | Samples
If you use the Azure CLI, replace <your-resource-group-name>
and <your-resource-name>
with your own unique names:
az search service create --resource-group <your-resource-group-name> --name <your-resource-name> --sku S
The above creates a resource with the "Standard" pricing tier. See choosing a pricing tier for more information.
@azure/search
packagenpm install @azure/search
SearchIndexClient
Azure Cognitive Search uses keys for authentication.
Use the Azure CLI snippet below to get the Admin Key from the Azure Cognitive Search resource.
az search admin-key show --resource-group <your-resource-group-name> --service-name <your-resource-name>
Alternatively, you can get the endpoint and Admin Key from the resource information in the Azure Portal.
Once you have an Admin Key, you can use it as follows:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
SearchIndexClient
is one of the primary interface for developers using the Azure Cognitive Search client library. It provides asynchronous methods for working with documents in an index. These methods allow you to query, upload, update, and delete documents. It also provides methods for building completion and suggestion experiences based on partial queries.
Typically you will only wish to show a subset of search results to a user at one time. To support this, you can use the top
, skip
and includeTotalResultCount
parameters to provide a paged experience on top of search results.
Supported data types in an index are mapped to JSON types in API requests/responses. The JS client library keeps these mostly the same, with some exceptions:
Edm.DateTimeOffset
is converted to a JS Date
.Edm.GeographyPoint
is converted to a GeographyPoint
type exported by the client library.number
type (NaN, Infinity, -Infinity) are serialized as strings in the REST API, but are converted back to number
by the client library.Note: Data types are converted based on value, not the field type in the index schema. This means that if you have an ISO8601 Date string (e.g. "2020-03-06T18:48:27.896Z") as the value of a field, it will be converted to a Date regardless of how you stored it in your schema.
To list all results of a particular query, you can use search
with a search string that uses simple query syntax:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const searchResults = await client.search({ searchText: "wifi -luxury" });
for await (const result of searchResults.results) {
console.log(result);
}
For a more advanced search that uses Lucene syntax, specify queryType
to be all
:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const searchResults = await client.search({
searchText: 'Category:budget AND "recently renovated"^3',
queryType: "full",
searchMode: "all"
});
for await (const result of searchResults.results) {
console.log(result);
}
In TypeScript SearchIndexClient
takes a generic parameter that is the model shape of your index documents. This allows you to perform strongly typed lookup of fields returned in results. TypeScript is also able to check for fields returned when specifying a select
parameter.
import { SearchIndexClient, SearchApiKeyCredential } from "@azure/search";
// An example schema for documents in the index
interface Hotel {
HotelId: string;
HotelName: string;
Description: string;
ParkingIncluded: boolean;
LastRenovationDate: Date;
Rating: number;
}
const client = new SearchIndexClient<Hotel>(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const searchResults = await client.search({
searchText: "wifi -luxury",
// Only fields in Hotel can be added to this array.
// TS will complain if one is misspelled.
select: ["HotelId", "HotelName", "Rating"]
});
for await (const result of searchResults.results) {
// result has HotelId, HotelName, and Rating.
// Trying to access result.Description would emit a TS error.
console.log(result.HotelName);
}
Using the filter
query parameter allows you to query an index using the syntax of an OData $filter expression.
const { SearchIndexClient, SearchApiKeyCredential, odata } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const baseRateMax = 200;
const ratingMin = 4;
const searchResults = await client.search({
searchText: "WiFi",
filter: odata`Rooms/any(room: room/BaseRate lt ${baseRateMax}) and Rating ge ${ratingMin}`,
orderBy: ["Rating desc"],
select: ["HotelId", "HotelName", "Rating"]
});
for await (const result of searchResults.results) {
// Each result will have "HotelId", "HotelName", and "Rating"
// in addition to the standard search result property "score"
console.log(result);
}
Facets are used to help a user of your application refine a search along pre-configured dimensions. Facet syntax provides the options to sort and bucket facet values.
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const searchResults = await client.search({
searchText: "WiFi",
facets: ["Category,count:3,sort:count", "Rooms/BaseRate,interval:100"]
});
console.log(searchResults.facets);
// Output will look like:
// {
// Rating: [
// { count: 4, value: 2 },
// { count: 5, value: 3 },
// { count: 8, value: 4 }
// ],
// 'Rooms/BaseRate': [
// { count: 16, value: 0 },
// { count: 17, value: 100 },
// { count: 17, value: 200 }
// ],
// Category: [
// { count: 5, value: 'Budget' },
// { count: 5, value: 'Luxury' },
// { count: 5, value: 'Resort and Spa' }
// ]
// }
When retrieving results, a facets
property will be available that will indicate the number of results that fall into each facet bucket. This can be used to drive refinement (e.g. issuing a follow-up search that filters on the Rating
being greater than or equal to 3 and less than 4.)
A specific document can be retrieved by its primary key value:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const result = await client.getDocument("1234");
console.log(result);
If you created a suggester on your index, you can use it to return result suggestions for a user query.
This example shows returning the top three suggestions for the input "wifi" from the suggester "sg":
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const suggestResult = await client.suggest({
searchText: "wifi",
suggesterName: "sg",
select: ["HotelId", "HotelName"],
highlightPreTag: "<em>",
highlightPostTag: "</em>",
top: 3
});
for (const result of suggestResult.results) {
console.log(`Suggestion: ${result.HotelName}; Match text: ${result.text}`);
}
To implement type-ahead behavior in your application, you can query the index with partial user input and return a list of suggested completions. You must have created a suggester on your index first.
The below example tries to complete the string "de" using the suggester named "sg" on the index:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const autocompleteResult = await client.autocomplete({
searchText: "de",
suggesterName: "sg"
});
for (const result of autocompleteResult.results || []) {
console.log(result.text);
}
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const count = await client.countDocuments();
console.log(`${count} documents in index ${client.indexName}`);
Given the name of a primary key and a list of indexes, you can delete multiple documents from the index at the same time:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const deleteResult = await client.deleteDocuments("HotelId", ["1", "2", "3"]);
for (const result of deleteResult.results) {
console.log(`Deleting ${result.key}; succeeded? ${result.succeeded}`);
}
You can upload multiple documents into index inside a batch:
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const uploadResult = await client.uploadDocuments([
// JSON objects matching the shape of the client's index
{ ... },
{ ... },
{ ... }
]);
for (const result of uploadResult.results) {
console.log(`Uploaded ${result.key}; succeeded? ${result.succeeded}`);
}
You can update multiple documents in an index at once, or create them if they do not exist. For more details about how merging works, see: https://docs.microsoft.com/rest/api/searchservice/AddUpdate-or-Delete-Documents
const { SearchIndexClient, SearchApiKeyCredential } = require("@azure/search");
const client = new SearchIndexClient(
"<endpoint>",
"<indexName>",
new SearchApiKeyCredential("<Admin Key>")
);
const updateResult = await client.mergeDocuments([
// JSON objects matching the shape of the client's index
{ ... },
{ ... },
{ ... }
], {
// update existing document if primary key exists
mergeIfExists: true,
// throw if updating any document in this batch fails
throwOnAnyFailure: true
});
for (const result of updateResult.results) {
console.log(`Update ${result.key}; succeeded? ${result.succeeded}`);
}
You can set the following environment variable to get the debug logs when using this library.
export AZURE_LOG_LEVEL=verbose*
For more detailed instructions on how to enable logs, you can look at the @azure/logger package docs.
Please take a look at the samples directory for detailed examples on how to use this library.
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
If you'd like to contribute to this library, please read the contributing guide to learn more about how to build and test the code.
Generated using TypeDoc