Query for Suggestions
-
Given a string term, the Suggestion feature will offer similar terms from your data.
-
Word similarities are found using string distance algorithms.
-
Examples in this article demonstrate getting suggestions with a dynamic-query.
For getting suggestions with an index-query see query for suggestions with index.
What are terms
-
All queries in RavenDB use an index - learn more about that here.
Whether making a dynamic query which generates an auto-index or using a static index,
the data from your documents is 'broken' into terms that are kept in the index. -
This tokenization process (what terms will be generated) depends on the analyzer used,
various analyzers differ in the way they split the text stream. Learn more in Analyzers. -
The terms can then be queried to retrieve matching documents that contain them.
When to use suggestions
Querying for suggestions is useful in the following scenarios:
-
When query has no results:
-
When searching for documents that match some condition on a given string term,
if the term is misspelled then you will Not get any results.
You can then ask RavenDB to suggest similar terms that do exist in the index. -
The suggested terms can then be used in a new query to retrieve matching documents,
or simply presented to the user asking what they meant to query.
-
-
When looking for alternative terms:
- When simply searching for additional alternative terms for a term that does exist.
The resulting suggested terms will Not include the term for which you search,
they will only contain the similar terms.
Suggest terms - for single term
Consider this example:
Based on the Northwind sample data, the following query has no resulting documents,
as no document in the Products collection contains the term chaig
in its Name
field.
// This dynamic query on the 'Products' collection has NO resulting documents
List<Product> products = session
.Query<Product>()
.Where(x => x.Name == "chaig")
.ToList();
-
Executing the above query will generate the auto-index
Auto/Products/ByName
.
This auto-index will contain a list of all available terms from the document fieldName
.
The generated terms are visible in the Studio - see image below. -
If you suspect that the term
chaig
in the query criteria is written incorrectly,
you can ask RavenDB to suggest existing terms that are similar tochaig
, as follows:.
// Query for suggested terms for single term:
// ==========================================
Dictionary<string, SuggestionResult> suggestions = session
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig'
.ByField(x => x.Name, "chaig"))
.Execute();
// Query for suggested terms for single term:
// ==========================================
Dictionary<string, SuggestionResult> suggestions = await asyncSession
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig'
.ByField(x => x.Name, "chaig"))
.ExecuteAsync();
// Define the suggestion request for single term
var suggestionRequest = new SuggestionWithTerm("Name")
{
// Looking for terms from field 'Name' that are similar to term 'chaig'
Term = "chaig"
};
// Query for suggestions
Dictionary<string, SuggestionResult> suggestions = session
.Query<Product>()
// Call 'SuggestUsing' - pass the suggestion request
.SuggestUsing(suggestionRequest)
.Execute();
// Query for suggested terms for single term:
// ==========================================
Dictionary<string, SuggestionResult> suggestions = session.Advanced
// Make a dynamic document-query on collection 'Products'
.DocumentQuery<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig'
.ByField(x => x.Name, "chaig"))
.Execute();
// Query for terms from field 'Name' that are similar to 'chaig'
from "Products"
select suggest(Name, "chaig")
// The resulting suggested terms:
// ==============================
Console.WriteLine("Suggested terms in field 'Name' that are similar to 'chaig':");
foreach (string suggestedTerm in suggestions["Name"].Suggestions)
{
Console.WriteLine("\t{0}", suggestedTerm);
}
// Suggested terms in field 'Name' that are similar to 'chaig':
// chai
// chang
Suggest terms - for multiple terms
// Query for suggested terms for multiple terms:
// =============================================
Dictionary<string, SuggestionResult> suggestions = session
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig' OR 'tof'
.ByField(x => x.Name, new[] { "chaig", "tof" }))
.Execute();
// Query for suggested terms for multiple terms:
// =============================================
Dictionary<string, SuggestionResult> suggestions = await asyncSession
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig' OR 'tof'
.ByField(x => x.Name, new[] { "chaig", "tof" }))
.ExecuteAsync();
// Define the suggestion request for multiple terms
var suggestionRequest = new SuggestionWithTerms("Name")
{
// Looking for terms from field 'Name' that are similar to terms 'chaig' OR 'tof'
Terms = new[] { "chaig", "tof"}
};
// Query for suggestions
Dictionary<string, SuggestionResult> suggestions = session
.Query<Product>()
// Call 'SuggestUsing' - pass the suggestion request
.SuggestUsing(suggestionRequest)
.Execute();
// Query for suggested terms for multiple terms:
// =============================================
Dictionary<string, SuggestionResult> suggestions = session.Advanced
// Make a dynamic document-query on collection 'Products'
.DocumentQuery<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
// Request to get terms from field 'Name' that are similar to 'chaig' OR 'tof'
.ByField(x => x.Name, new[] { "chaig", "tof" }))
.Execute();
// Query for terms from field 'Name' that are similar to 'chaig' OR 'tof'
from "Products" select suggest(Name, $p0)
{ "p0" : ["chaig", "tof"] }
// The resulting suggested terms:
// ==============================
// Suggested terms in field 'Name' that are similar to 'chaig' OR to 'tof':
// chai
// chang
// tofu
Suggest terms - for multiple fields
// Query for suggested terms in multiple fields:
// =============================================
Dictionary<string, SuggestionResult> suggestions = session
// Make a dynamic query on collection 'Companies'
.Query<Company>()
// Call 'SuggestUsing' to get suggestions for terms that are
// similar to 'chop-soy china' in first document field (e.g. 'Name')
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chop-soy china"))
// Call 'AndSuggestUsing' to get suggestions for terms that are
// similar to 'maria larson' in an additional field (e.g. 'Contact.Name')
.AndSuggestUsing(builder => builder
.ByField(x => x.Contact.Name, "maria larson"))
.Execute();
// Query for suggested terms in multiple fields:
// =============================================
Dictionary<string, SuggestionResult> suggestions = await asyncSession
// Make a dynamic query on collection 'Companies'
.Query<Company>()
// Call 'SuggestUsing' to get suggestions for terms that are
// similar to 'chop-soy china' in first document field (e.g. 'Name')
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chop-soy china"))
// Call 'AndSuggestUsing' to get suggestions for terms that are
// similar to 'maria larson' in an additional field (e.g. 'Contact.Name')
.AndSuggestUsing(builder => builder
.ByField(x => x.Contact.Name, "maria larson"))
.ExecuteAsync();
// Define suggestion requests for multiple fields:
var request1 = new SuggestionWithTerm("Name")
{
// Looking for terms from field 'Name' that are similar to 'chop-soy china'
Term = "chop-soy china"
};
var request2 = new SuggestionWithTerm("Contact.Name")
{
// Looking for terms from nested field 'Contact.Name' that are similar to 'maria larson'
Term = "maria larson"
};
Dictionary<string, SuggestionResult> suggestions = session
.Query<Company>()
// Call 'SuggestUsing' - pass the suggestion request for the first field
.SuggestUsing(request1)
// Call 'AndSuggestUsing' - pass the suggestion request for the second field
.AndSuggestUsing(request2)
.Execute();
// Query for suggested terms in multiple fields:
// =============================================
Dictionary<string, SuggestionResult> suggestions = session.Advanced
// Make a dynamic document-query on collection 'Companies'
.DocumentQuery<Company>()
// Call 'SuggestUsing' to get suggestions for terms that are
// similar to 'chop-soy china' in first document field (e.g. 'Name')
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chop-soy china"))
// Call 'AndSuggestUsing' to get suggestions for terms that are
// similar to 'maria larson' in an additional field (e.g. 'Contact.Name')
.AndSuggestUsing(builder => builder
.ByField(x => x.Contact.Name, "maria larson"))
.Execute();
// Query for suggested terms from field 'Name' and field 'Contact.Name'
from "Companies"
select suggest(Name, "chop-soy china"), suggest(Contact.Name, "maria larson")
// The resulting suggested terms:
// ==============================
// Suggested terms in field 'Name' that is similar to 'chop-soy china':
// chop-suey chinese
// Suggested terms in field 'Contact.Name' that are similar to 'maria larson':
// maria larsson
// marie bertrand
// aria cruz
// paula wilson
// maria anders
Suggest terms - customize options and display name
// Query for suggested terms - customize options and display name:
// ===============================================================
Dictionary<string, SuggestionResult> suggestions = session
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chaig")
// Customize suggestions options
.WithOptions(new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
})
// Customize display name for results
.WithDisplayName("SomeCustomName"))
.Execute();
// Query for suggested terms - customize options and display name:
// ===============================================================
Dictionary<string, SuggestionResult> suggestions = await asyncSession
// Make a dynamic query on collection 'Products'
.Query<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chaig")
// Customize suggestions options
.WithOptions(new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
})
// Customize display name for results
.WithDisplayName("SomeCustomName"))
.ExecuteAsync();
// Define the suggestion request
var suggestionRequest = new SuggestionWithTerm("Name")
{
// Looking for terms from field 'Name' that are similar to term 'chaig'
Term = "chaig",
// Customize options
Options = new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
},
// Customize display name
DisplayField = "SomeCustomName"
};
// Query for suggestions
Dictionary<string, SuggestionResult> suggestions = session
.Query<Product>()
// Call 'SuggestUsing' - pass the suggestion request
.SuggestUsing(suggestionRequest)
.Execute();
// Query for suggested terms - customize options and display name:
// ===============================================================
Dictionary<string, SuggestionResult> suggestions = session.Advanced
// Make a dynamic query on collection 'Products'
.DocumentQuery<Product>()
// Call 'SuggestUsing'
.SuggestUsing(builder => builder
.ByField(x => x.Name, "chaig")
// Customize suggestions options
.WithOptions(new SuggestionOptions
{
Accuracy = 0.4f,
PageSize = 5,
Distance = StringDistanceTypes.JaroWinkler,
SortMode = SuggestionSortMode.Popularity
})
// Customize display name for results
.WithDisplayName("SomeCustomName"))
.Execute();
// Query for suggested terms - customize options and display name
from "Products"
select suggest(
Name,
'chaig',
'{ "Accuracy" : 0.4, "PageSize" : 5, "Distance" : "JaroWinkler", "SortMode" : "Popularity" }'
) as "SomeCustomName"
// The resulting suggested terms:
// ==============================
Console.WriteLine("Suggested terms:");
// Results are available under the custom name entry
foreach (string suggestedTerm in suggestions["SomeCustomName"].Suggestions)
{
Console.WriteLine("\t{0}", suggestedTerm);
}
// Suggested terms:
// chai
// chang
// chartreuse verte
The auto-index terms in Studio
Based on the Northwind sample data, these are the terms generated for index Auto/Products/ByName
:
Terms generated for index Auto/Products/ByName
-
The field name - derived from the document field that was used in the dynamic-query.
In this example the field name isName
. -
The terms generated from the data that the Products collection documents have in their
Name
field.
Syntax
Suggest using:
// Overloads for requesting suggestions for term(s) in a field:
ISuggestionQuery<T> SuggestUsing<T>(SuggestionBase suggestion);
ISuggestionQuery<T> SuggestUsing<T>(Action<ISuggestionBuilder<T>> builder);
// Overloads requesting suggestions for term(s) in another field in the same query:
ISuggestionQuery<T> AndSuggestUsing(SuggestionBase suggestion);
ISuggestionQuery<T> AndSuggestUsing(Action<ISuggestionBuilder<T>> builder);
Parameter | Type | Description |
---|---|---|
suggestion | SuggestionWithTerm / SuggestionWithTerms |
An instance of SuggestionBase .Defines the type of suggestion requested. |
builder | Action<ISuggestionBuilder<T>> |
Builder with a fluent API that constructs a SuggestionBase instance. |
Builder operations:
ISuggestionOperations<T> ByField(string fieldName, string term);
ISuggestionOperations<T> ByField(string fieldName, string[] terms);
ISuggestionOperations<T> ByField(Expression<Func<T, object>> path, string term);
ISuggestionOperations<T> ByField(Expression<Func<T, object>> path, string[] terms);
ISuggestionOperations<T> WithDisplayName(string displayName);
ISuggestionOperations<T> WithOptions(SuggestionOptions options);
Parameter | Type | Description |
---|---|---|
fieldName | string |
The index field in which to search for similar terms |
path | Expression<Func<T, object>> |
The index field in which to search for similar terms |
term | string |
The term for which to get suggested similar terms |
terms | string[] |
List of terms for which to get suggested similar terms |
displayName | string |
A custom name for the suggestions result (optional). |
options | SuggestionOptions |
Non-default options to use in the operation (optional). |
Suggestions options:
public int PageSize { get; set; }
public StringDistanceTypes? Distance { get; set; }
public float? Accuracy { get; set; }
public SuggestionSortMode SortMode { get; set; }
Option | Type | Description |
---|---|---|
PageSize | int |
|
Distance | StringDistanceTypes |
|
Accuracy | float? |
|
SortMode | SuggestionSortMode |
|