Querying: Suggestions
RavenDB has an indexing mechanism built upon the Lucene engine which has a great suggestions feature. This capability allows a significant improvement of search functionalities enhancing the overall user experience of the application.
Let's consider an example where the users have the option to look for products by their name. The index and query would appear as follows:
0
// Define the suggestion request for multiple terms
var suggestionRequest = new SuggestionWithTerms("ProductName")
{
// Looking for terms from index-field 'ProductName' that are similar to 'chokolade' OR 'syrop'
Terms = new[] { "chokolade", "syrop"}
};
// Query the index for suggestions
Dictionary<string, SuggestionResult> suggestions = session
.Query<Products_ByName.IndexEntry, Products_ByName>()
// Call 'SuggestUsing' - pass the suggestion request
.SuggestUsing(suggestionRequest)
.Execute();
// This query on index 'Products/ByName' has NO resulting documents
List<Product> products = session
.Query<Products_ByName.IndexEntry, Products_ByName>()
.Search(x => x.ProductName, "chokolade")
.OfType<Product>()
.ToList();
If our database has Northwind
samples deployed then it will not return any results. However, we can ask RavenDB for help:
- Query
- DocumentQuery
- RQL
if (product == null)
{
Dictionary<string, SuggestionResult> suggestionResult = session
.Query<Product, Products_ByName>()
.SuggestUsing(builder => builder.ByField(x => x.Name, "chaig"))
.Execute();
Console.WriteLine("Did you mean?");
foreach (string suggestion in suggestionResult["Name"].Suggestions)
{
Console.WriteLine("\t{0}", suggestion);
}
}
if (product == null)
{
Dictionary<string, SuggestionResult> suggestionResult = session.Advanced
.DocumentQuery<Product, Products_ByName>()
.SuggestUsing(builder => builder.ByField(x => x.Name, "chaig"))
.Execute();
Console.WriteLine("Did you mean?");
foreach (string suggestion in suggestionResult["Name"].Suggestions)
{
Console.WriteLine("\t{0}", suggestion);
}
}
from index 'Products/ByName'
select suggest('Name', 'chaig')
It will produce these suggestions:
Did you mean? chang chai
The SuggestUsing
method is an extension contained in the Raven.Client.Documents
namespace. You can read more about it in our Client API article.
Suggest Over Multiple Words
RavenDB allows you to perform a suggestion query over multiple words.
- Query
- DocumentQuery
var resultsByMultipleWords = session
.Query<Product, Products_ByName>()
.SuggestUsing(builder => builder
.ByField(x => x.Name, new[] { "chaig", "tof" })
.WithOptions(new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
}))
.Execute();
Console.WriteLine("Did you mean?");
foreach (string suggestion in resultsByMultipleWords["Name"].Suggestions)
{
Console.WriteLine("\t{0}", suggestion);
}
var resultsByMultipleWords = session.Advanced
.DocumentQuery<Product, Products_ByName>()
.SuggestUsing(builder => builder
.ByField(x => x.Name, new[] { "chaig", "tof" })
.WithOptions(new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
}))
.Execute();
Console.WriteLine("Did you mean?");
foreach (string suggestion in resultsByMultipleWords["Name"].Suggestions)
{
Console.WriteLine("\t{0}", suggestion);
}
This will produce the following results:
Did you mean? chai chang chartreuse chef tofu
Remarks
Indexes with turned on suggestions tend to use a lot more CPU power than other indexes. This can impact indexing speed (querying is not impacted).