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.
The Azure Cognitive Search service is well suited for the following application scenarios:
Use the @azure/search-documents client library to:
Source code | Package (NPM) | API reference documentation | REST API documentation | Product documentation | Samples
@azure/search-documents
packagenpm install @azure/search-documents
This package supports Node.js version 8.x.x or higher. You need an Azure subscription and a search service to use this package.
To create a new search service, you can use the Azure portal, Azure PowerShell, or the Azure CLI. Here's an example using the Azure CLI to create a free instance for getting started:
az search service create --name <mysearch> --resource-group <mysearch-rg> --sku free --location westus
See choosing a pricing tier for more information about available options.
All requests to a search service need an API key that was generated specifically for your service. The API key is the sole mechanism for authenticating access to your search service endpoint.
You can obtain your api-key from the Azure portal or via the Azure CLI:
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.
There are two types of keys used to access your search service: admin (read-write) and query (read-only) keys. Restricting access and operations in client apps is essential to safeguarding the search assets on your service. Always use a query key rather than an admin key for any query originating from a client app.
Note: The example Azure CLI snippet above retrieves an admin key so it's easier to get started exploring APIs, but it should be managed carefully.
Once you have an api-key, you can use it as follows:
const {
SearchClient,
SearchIndexClient,
SearchServiceClient,
AzureKeyCredential,
} = require("@azure/search-documents");
// To query and manipulate documents
const searchClient = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
// To manage indexes and synonymmaps
const indexClient = new SearchIndexClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
// To manage indexers, datasources and skillsets
const indexerClient = new SearchIndexerClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
To get running immediately, we're going to connect to a well known sandbox Search service provided by Microsoft. This means you do not need an Azure subscription or Azure Cognitive Search service to try out this query.
const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
// We'll connect to the Azure Cognitive Search public sandbox and send a
// query to its "nycjobs" index built from a public dataset of available jobs
// in New York.
const indexName = "nycjobs";
const apiKey = "252044BE3886FE4A8E3BAA4F595114BB";
// Create a SearchClient to send queries
const client = new SearchClient(
`https://azs-playground.search.windows.net/`,
indexName,
new AzureKeyCredential(apiKey)
);
async function main() {
// Let's get the top 5 jobs related to Microsoft
const searchResults = await client.search("Microsoft", { top: 5 });
for await (const result of searchResults.results) {
console.log(`${result.document.business_title}\n${result.document.job_description}\n`);
}
}
main();
An Azure Cognitive Search service contains one or more indexes that provide persistent storage of searchable data in the form of JSON documents. (If you're brand new to search, you can make a very rough analogy between indexes and database tables.) The @azure/search-documents client library exposes operations on these resources through three main client types.
SearchClient
helps with:SearchIndexClient
allows you to:
SearchIndexerClient
allows you to:
Note: These clients cannot function in the browser because the APIs it calls do not have support for Cross-Origin Resource Sharing (CORS).
An item stored inside a search index. The shape of this document is described in the index using Field
s. Each Field has a name, a datatype, and additional metadata such as if it is searchable or filterable.
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 includeTotalCount
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.
The following examples demonstrate the basics - please check out our samples for much more.
const { SearchIndexClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchIndexClient("<endpoint>", new AzureKeyCredential("<apiKey>"));
async function main() {
const result = await client.createIndex({
name: "example-index",
fields: [
{
type: "Edm.String",
name: "id",
key: true,
},
{
type: "Edm.Double",
name: "awesomenessLevel",
sortable: true,
filterable: true,
facetable: true,
},
{
type: "Edm.String",
name: "description",
searchable: true,
},
{
type: "Edm.ComplexType",
name: "details",
fields: [
{
type: "Collection(Edm.String)",
name: "tags",
searchable: true,
},
],
},
{
type: "Edm.Int32",
name: "hiddenWeight",
hidden: true,
},
],
});
console.log(result);
}
main();
A specific document can be retrieved by its primary key value:
const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const result = await client.getDocument("1234");
console.log(result);
}
main();
You can upload multiple documents into index inside a batch:
const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
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}`);
}
}
main();
To list all results of a particular query, you can use search
with a search string that uses simple query syntax:
const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const searchResults = await client.search("wifi -luxury");
for await (const result of searchResults.results) {
console.log(result);
}
}
main();
For a more advanced search that uses Lucene syntax, specify queryType
to be full
:
const { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const searchResults = await client.search('Category:budget AND "recently renovated"^3', {
queryType: "full",
searchMode: "all",
});
for await (const result of searchResults.results) {
console.log(result);
}
}
main();
In TypeScript SearchClient
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 { SearchClient, AzureKeyCredential } from "@azure/search-documents";
// 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 SearchClient<Hotel>(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const searchResults = await client.search("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.document has HotelId, HotelName, and Rating.
// Trying to access result.document.Description would emit a TS error.
console.log(result.document.HotelName);
}
}
main();
Using the filter
query parameter allows you to query an index using the syntax of an OData $filter expression.
const { SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const baseRateMax = 200;
const ratingMin = 4;
const searchResults = await client.search("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);
}
}
main();
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 { SearchClient, AzureKeyCredential } = require("@azure/search-documents");
const client = new SearchClient(
"<endpoint>",
"<indexName>",
new AzureKeyCredential("<apiKey>")
);
async function main() {
const searchResults = await client.search("WiFi", {
facets: ["Category,count:3,sort:count", "Rooms/BaseRate,interval:100"],
});
console.log(searchResults.facets);
// Output will look like:
// {
// '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' }
// ]
// }
}
main();
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.)
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.
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.
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 cla.microsoft.com.
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.
Generated using TypeDoc