Create data-driven experiences with Azure Search in the v3 JavaScript SDK
APPLIES TO: SDK v3
You can add Azure Search to your bot to help the user navigate large amounts of content and create a data-driven exploration experience for users of your bot.
Azure Search is an Azure service that offers keyword search, built-in linguistics, custom scoring, faceted navigation and more. Azure Search can also index content from various sources, including Azure SQL DB, DocumentDB, Blob Storage, and Table Storage. It supports "push" indexing for other sources of data, and it can open PDFs, Office documents, and other formats containing unstructured data. Once collected, the content goes into an Azure Search index, which the bot can then query.
Install dependencies
From a command prompt, navigate to your bot's project directory and install the following modules with the Node Package Manager (NPM):
Prerequisites
The following are required:
Have an Azure subscription and an Azure Search Primary Key. You can find this in the Azure portal.
Copy the SearchDialogLibrary library to your bot's project directory. This library contains general dialogs for the user to search, but can be customized as needed to suit your bot.
Copy the SearchProviders library to your bot's project directory. This library contains all of the components required to create a request and submit it to Azure Search.
Connect to the Azure Service
In your bot's main program file (e.g.: app.js), create the reference paths to the two libraries you installed previously.
var SearchLibrary = require('./SearchDialogLibrary');
var AzureSearch = require('./SearchProviders/azure-search');
Add the following sample code to your bot. In the AzureSearch
object, pass in your own Azure Search settings into the .create
method. At run time, this will bind your bot to the Azure Search service and wait for a completed user query in the form of a Promise
.
// Azure Search
var azureSearchClient = AzureSearch.create('Your-Azure-Search-Service-Name', 'Your-Azure-Search-Primary-Key', 'Your-Azure-Search-Service-Index');
var ResultsMapper = SearchLibrary.defaultResultsMapper(ToSearchHit);
The azureSearchClient
reference creates the Azure Search model, which passes the Azure Service's authorization settings from the bot's .env
settings.
ResultsMapper
parses the Azure response object and maps the data as we define in ToSearchHit
method. For an implementation example of this method, see After Azure Search responds.
Register the search library
You can customize your search dialogs directly in the SearchLibrary
module itself. The SearchLibrary
performs most of the heavy lifting, including making the call to Azure Search.
Add the following code in your bot's main program file to register the Search Dialogs library with your bot.
bot.library(SearchLibrary.create({
multipleSelection: true,
search: function (query) { return azureSearchClient.search(query).then(ResultsMapper); },
refiners: ['refiner1', 'refiner2', 'refiner3'], // customize your own refiners
refineFormatter: function (refiners) {
return _.zipObject(
refiners.map(function (r) { return 'By ' + _.capitalize(r); }),
refiners);
}
}));
The SearchLibrary
not only stores all of your search related dialogs, but also takes the user query to submit to Azure Search. You will need to define your own refiners in the refiners
array to specify entities you wish to allow your user to narrow or filter their search results.
Create a search dialog
You may choose to structure your dialogs however you want. The only requirement to setting up an Azure Search dialog is to invoke the .begin
method
from the SearchLibrary
object, passing in the session
object generated by the Bot Framework SDK.
function (session) {
// Trigger Azure Search dialogs
SearchLibrary.begin(session);
},
function (session, args) {
// Process selected search results
session.send(
'Search Completed!',
args.selection.map( ); // format your response
}
For more information about dialogs, see Manage a conversation with dialogs.
After Azure Search responds
Once a successful Azure Search resolves, you now need to store the data you want from the response object, and display it in a meaningful way to the user.
Tip
Consider including the util module. It will help you format and map the response from Azure Search.
In your bot's main program file, create a ToSearchHit
method. This method returns an object which formats the relevant data you need from the Azure Response. The following code shows how you can define your own parameters in the ToSearchHit
method.
function ToSearchHit(azureResponse) {
return {
// define your own parameters
key: azureResponse.id,
title: azureResponse.title,
description: azureResponse.description,
imageUrl: azureResponse.thumbnail
};
}
After this is done, all you need to do is display the data to the user.
In the index.js file of the SearchDialogLibrary project, the searchHitAsCard
method parses each response from the Azure Search and creates a new card object to display to the user. The fields you defined in the ToSearchHit
method from your bot's main program file needs to synced with the properties in the searchHitAsCard
method.
The following shows how and where your defined parameters from the ToSearchHit
method are used to build a card attachment UI to render to the user.
function searchHitAsCard(showSave, searchHit) {
var buttons = showSave
? [new builder.CardAction().type('imBack').title('Save').value(searchHit.key)]
: [];
var card = new builder.HeroCard()
.title(searchHit.title)
.buttons(buttons);
if (searchHit.description) {
card.subtitle(searchHit.description);
}
if (searchHit.imageUrl) {
card.images([new builder.CardImage().url(searchHit.imageUrl)]);
}
return card;
}
Sample code
For two complete samples that show how to support Azure Search with bots using the Bot Framework SDK for Node.js, see the Real Estate Bot sample or Job Listing Bot sample in GitHub.