Example: Add synonyms for Azure Cognitive Search in C#
Synonyms expand a query by matching on terms considered semantically equivalent to the input term. For example, you might want "car" to match documents containing the terms "automobile" or "vehicle".
In Azure Cognitive Search, synonyms are defined in a synonym map, through mapping rules that associate equivalent terms. This example covers essential steps for adding and using synonyms with an existing index.
In this example, you will learn how to:
- Create a synonym map using the SynonymMap class.
- Set the SynonymMapsName property on fields that should support query expansion via synonyms.
You can query a synonym-enabled field as you would normally. There is no additional query syntax required to access synonyms.
You can create multiple synonym maps, post them as a service-wide resource available to any index, and then reference which one to use at the field level. At query time, in addition to searching an index, Azure Cognitive Search does a lookup in a synonym map, if one is specified on fields used in the query.
Note
Synonyms can be created programmatically, but not in the portal.
Prerequisites
Tutorial requirements include the following:
If you are unfamiliar with the .NET client library, see How to use Azure Cognitive Search in .NET.
Sample code
You can find the full source code of the sample application used in this example on GitHub.
Overview
Before-and-after queries are used to demonstrate the value of synonyms. In this example, a sample application executes queries and returns results on a sample "hotels" index populated with two documents. First, the application executes search queries using terms and phrases that do not appear in the index. Second, the code enables the synonyms feature, then re-issues the same queries, this time returning results based on matches in the synonym map.
The code below demonstrates the overall flow.
static void Main(string[] args)
{
SearchIndexClient indexClient = CreateSearchIndexClient();
Console.WriteLine("Cleaning up resources...\n");
CleanupResources(indexClient);
Console.WriteLine("Creating index...\n");
CreateHotelsIndex(indexClient);
SearchClient searchClient = indexClient.GetSearchClient("hotels");
Console.WriteLine("Uploading documents...\n");
UploadDocuments(searchClient);
SearchClient searchClientForQueries = CreateSearchClientForQueries();
RunQueriesWithNonExistentTermsInIndex(searchClientForQueries);
Console.WriteLine("Adding synonyms...\n");
UploadSynonyms(indexClient);
Console.WriteLine("Enabling synonyms in the test index...\n");
EnableSynonymsInHotelsIndexSafely(indexClient);
Thread.Sleep(10000); // Wait for the changes to propagate
RunQueriesWithNonExistentTermsInIndex(searchClientForQueries);
Console.WriteLine("Complete. Press any key to end application...\n");
Console.ReadKey();
}
"Before" queries
In RunQueriesWithNonExistentTermsInIndex
, issue search queries with "five star", "internet", and "economy AND hotel".
Phrase queries, such as "five star", must be enclosed in quotation marks, and might also need escape characters depending on your client.
Console.WriteLine("Search the entire index for the phrase \"five star\":\n");
results = searchClient.Search<Hotel>("\"five star\"", searchOptions);
WriteDocuments(results);
Console.WriteLine("Search the entire index for the term 'internet':\n");
results = searchClient.Search<Hotel>("internet", searchOptions);
WriteDocuments(results);
Console.WriteLine("Search the entire index for the terms 'economy' AND 'hotel':\n");
results = searchClient.Search<Hotel>("economy AND hotel", searchOptions);
WriteDocuments(results);
Neither of the two indexed documents contain the terms, so we get the following output from the first RunQueriesWithNonExistentTermsInIndex
: no document matched.
Enable synonyms
After the "before" queries are run, the sample code enables synonyms. Enabling synonyms is a two-step process. First, define and upload synonym rules. Second, configure fields to use them. The process is outlined in UploadSynonyms
and EnableSynonymsInHotelsIndex
.
Add a synonym map to your search service. In
UploadSynonyms
, we define four rules in our synonym map 'desc-synonymmap' and upload to the service.private static void UploadSynonyms(SearchIndexClient indexClient) { var synonymMap = new SynonymMap("desc-synonymmap", "hotel, motel\ninternet,wifi\nfive star=>luxury\neconomy,inexpensive=>budget"); indexClient.CreateOrUpdateSynonymMap(synonymMap); }
Configure searchable fields to use the synonym map in the index definition. In
AddSynonymMapsToFields
, we enable synonyms on two fieldscategory
andtags
by setting theSynonymMapNames
property to the name of the newly uploaded synonym map.private static SearchIndex AddSynonymMapsToFields(SearchIndex index) { index.Fields.First(f => f.Name == "category").SynonymMapNames.Add("desc-synonymmap"); index.Fields.First(f => f.Name == "tags").SynonymMapNames.Add("desc-synonymmap"); return index; }
When you add a synonym map, index rebuilds are not required. You can add a synonym map to your service, and then amend existing field definitions in any index to use the new synonym map. The addition of new attributes has no impact on index availability. The same applies in disabling synonyms for a field. You can simply set the
SynonymMapNames
property to an empty list.index.Fields.First(f => f.Name == "category").SynonymMapNames.Add("desc-synonymmap");
"After" queries
After the synonym map is uploaded and the index is updated to use the synonym map, the second RunQueriesWithNonExistentTermsInIndex
call outputs the following:
Search the entire index for the phrase "five star":
Name: Fancy Stay Category: Luxury Tags: [pool, view, wifi, concierge]
Search the entire index for the term 'internet':
Name: Fancy Stay Category: Luxury Tags: [pool, view, wifi, concierge]
Search the entire index for the terms 'economy' AND 'hotel':
Name: Roach Motel Category: Budget Tags: [motel, budget]
The first query finds the document from the rule five star=>luxury
. The second query expands the search using internet,wifi
and the third using both hotel, motel
and economy,inexpensive=>budget
in finding the documents they matched.
Adding synonyms completely changes the search experience. In this example, the original queries failed to return meaningful results even though the documents in our index were relevant. By enabling synonyms, we can expand an index to include terms in common use, with no changes to underlying data in the index.
Clean up resources
The fastest way to clean up after an example is by deleting the resource group containing the Azure Cognitive Search service. You can delete the resource group now to permanently delete everything in it. In the portal, the resource group name is on the Overview page of Azure Cognitive Search service.
Next steps
This example demonstrated the synonyms feature in C# code to create and post mapping rules and then call the synonym map on a query. Additional information can be found in the .NET SDK and REST API reference documentation.
Feedback
Submit and view feedback for