Include Explanations in Index Query
-
This article provides examples of including explanations when querying a static-index.
-
Prior to this article, please refer to Include Query Explanations for dynamic-query examples
and general knowledge about including explanations to retrieve the score of resulting documents.- Including explanations is available only when using Lucene as the underlying search engine for static-indexes.
- You can configure which search engine will be used. Learn how in Selecting the search engine.
Include explanations when querying Map index
public class Products_BySearchName : AbstractIndexCreationTask<Product>
{
public class IndexEntry
{
public string Name { get; set; }
}
public Products_BySearchName()
{
Map = products => from product in products
select new IndexEntry()
{
Name = product.Name
};
// Configure the index-field 'Name' for FTS
Indexes.Add(x => x.Name, FieldIndexing.Search);
}
}
List<Product> products = session
// Query the index
.Query<Products_BySearchName.IndexEntry, Products_BySearchName>()
// Convert the IRavenQueryable to IDocumentQuery
// to be able to use 'IncludeExplanations'
.ToDocumentQuery()
// Call 'IncludeExplanations', provide an out param for the explanations results
.IncludeExplanations(out Explanations explanations)
// Convert back to IRavenQueryable
// to continue building the query using LINQ
.ToQueryable()
// Define query criteria
// e.g. search for docs containing Syrup -or- Lager in their Name field
.Search(x => x.Name, "Syrup Lager" )
.OfType<Product>()
.ToList();
// When running the above query on the RavenDB sample data
// the results contain 3 product documents.
// To get the score details for the first document from the results
// call 'GetExplanations' on the resulting Explanations object as follows:
string[] scoreDetails = explanations.GetExplanations(products[0].Id);
List<Product> products = await asyncSession
// Query the index
.Query<Products_BySearchName.IndexEntry, Products_BySearchName>()
// Convert the IRavenQueryable to IDocumentQuery
// to be able to use 'IncludeExplanations'
.ToAsyncDocumentQuery()
// Call 'IncludeExplanations', provide an out param for the explanations results
.IncludeExplanations(out Explanations explanations)
// Convert back to IRavenQueryable
// to continue building the query using LINQ
.ToQueryable()
// Define query criteria
// e.g. search for docs containing Syrup -or- Lager in their Name field
.Search(x => x.Name, "Syrup Lager" )
.OfType<Product>()
.ToListAsync();
// When running the above query on the RavenDB sample data
// the results contain 3 product documents.
// To get the score details for the first document from the results
// call 'GetExplanations' on the resulting Explanations object as follows:
string[] scoreDetails = explanations.GetExplanations(products[0].Id);
List<Product> products = session.Advanced
// Query the index
.DocumentQuery<Products_BySearchName.IndexEntry, Products_BySearchName>()
// Call 'IncludeExplanations', provide an out param for the explanations results
.IncludeExplanations(out Explanations explanations)
// Define query criteria
// e.g. search for docs containing Syrup -or- Lager in their Name field
.Search(x => x.Name, "Syrup Lager" )
.OfType<Product>()
.ToList();
// When running the above query on the RavenDB sample data
// the results contain 3 product documents.
// To get the score details for the first document from the results
// call 'GetExplanations' on the resulting Explanations object as follows:
string[] scoreDetails = explanations.GetExplanations(products[0].Id);
List<Product> products = await asyncSession.Advanced
// Query the index
.AsyncDocumentQuery<Products_BySearchName.IndexEntry, Products_BySearchName>()
// Call 'IncludeExplanations', provide an out param for the explanations results
.IncludeExplanations(out Explanations explanations)
// Define query criteria
// e.g. search for docs containing Syrup -or- Lager in their Name field
.Search(x => x.Name, "Syrup Lager" )
.OfType<Product>()
.ToListAsync();
// When running the above query on the RavenDB sample data
// the results contain 3 product documents.
// To get the score details for the first document from the results
// call 'GetExplanations' on the resulting Explanations object as follows:
string[] scoreDetails = explanations.GetExplanations(products[0].Id);
from index "Products/BySearchName"
where search(Name, "Syrup Lager")
include explanations()
// Or:
from index "Products/BySearchName"
where search(Name, "Syrup") or search(Name, "Lager")
include explanations()
Include explanations when querying Map-Reduce index
// This index counts the number of units ordered per category in all Product documents
// ===================================================================================
public class NumberOfUnitsOrdered_PerCategory :
AbstractIndexCreationTask<Product, NumberOfUnitsOrdered_PerCategory.IndexEntry>
{
public class IndexEntry
{
public string Category { get; set; }
public int NumberOfUnitsOrdered { get; set; }
}
public NumberOfUnitsOrdered_PerCategory()
{
Map = products => from product in products
// Load the products' category
let categoryName = LoadDocument<Category>(product.Category).Name
select new IndexEntry()
{
Category = categoryName,
NumberOfUnitsOrdered = product.UnitsOnOrder
};
Reduce = results => from result in results
group result by result.Category
into g
let unitsOrdered = g.Sum(x => x.NumberOfUnitsOrdered)
select new IndexEntry()
{
Category = g.Key,
NumberOfUnitsOrdered = unitsOrdered
};
}
}
List<NumberOfUnitsOrdered_PerCategory.IndexEntry> results = session
// Query the Map-Reduce index
.Query<NumberOfUnitsOrdered_PerCategory.IndexEntry,
NumberOfUnitsOrdered_PerCategory>()
// Convert the IRavenQueryable to IDocumentQuery
// to be able to use 'IncludeExplanations'
.ToDocumentQuery()
// Call 'IncludeExplanations', provide:
// * The group key for each result item
// * An out param for the explanations results
.IncludeExplanations(
new ExplanationOptions { GroupKey = "Category" },
out Explanations explanations)
// Convert back to IRavenQueryable
// to continue building the query using LINQ
.ToQueryable()
// Query for categories that have a total of more than a 400 units ordered
.Where(x => x.NumberOfUnitsOrdered > 400)
.ToList();
// Get the score details for an item in the results
// Pass the group key (Category, in this case) to 'GetExplanations'
string[] scoreDetails = explanations.GetExplanations(results[0].Category);
List<NumberOfUnitsOrdered_PerCategory.IndexEntry> results = await asyncSession
// Query the Map-Reduce index
.Query<NumberOfUnitsOrdered_PerCategory.IndexEntry,
NumberOfUnitsOrdered_PerCategory>()
// Convert the IRavenQueryable to IDocumentQuery
// to be able to use 'IncludeExplanations'
.ToAsyncDocumentQuery()
// Call 'IncludeExplanations', provide:
// * The group key for each result item
// * An out param for the explanations results
.IncludeExplanations(
new ExplanationOptions { GroupKey = "Category" },
out Explanations explanations)
// Convert back to IRavenQueryable
// to continue building the query using LINQ
.ToQueryable()
// Query for categories that have a total of more than a 400 units ordered
.Where(x => x.NumberOfUnitsOrdered > 400)
.ToListAsync();
// Get the score details for an item in the results
// Pass the group key (Category, in this case) to 'GetExplanations'
string[] scoreDetails = explanations.GetExplanations(results[0].Category);
List<NumberOfUnitsOrdered_PerCategory.IndexEntry> results = session.Advanced
// Query the Map-Reduce index
.DocumentQuery<NumberOfUnitsOrdered_PerCategory.IndexEntry,
NumberOfUnitsOrdered_PerCategory>()
// Call 'IncludeExplanations', provide:
// * The group key for each result item
// * An out param for the explanations results
.IncludeExplanations(
new ExplanationOptions { GroupKey = "Category" },
out Explanations explanations)
// Query for categories that have a total of more than a 400 units ordered
.WhereGreaterThan(x => x.NumberOfUnitsOrdered, 400)
.ToList();
// Get the score details for an item in the results
// Pass the group key (Category, in this case) to 'GetExplanations'
string[] scoreDetails = explanations.GetExplanations(results[0].Category);
List<NumberOfUnitsOrdered_PerCategory.IndexEntry> results = await asyncSession.Advanced
// Query the Map-Reduce index
.AsyncDocumentQuery<NumberOfUnitsOrdered_PerCategory.IndexEntry,
NumberOfUnitsOrdered_PerCategory>()
// Call 'IncludeExplanations', provide:
// * The group key for each result item
// * An out param for the explanations results
.IncludeExplanations(
new ExplanationOptions { GroupKey = "Category" },
out Explanations explanations)
// Query for categories that have a total of more than a 400 units ordered
.WhereGreaterThan(x => x.NumberOfUnitsOrdered, 400)
.ToListAsync();
// Get the score details for an item in the results
// Pass the group key (Category, in this case) to 'GetExplanations'
string[] scoreDetails = explanations.GetExplanations(results[0].Category);
from index "NumberOfUnitsOrdered/PerCategory"
where NumberOfUnitsOrdered > 400
include explanations($p0)
{"p0" : { "GroupKey" : "Category" }}
Syntax
// Use this overload when querying a Map index
IDocumentQuery<T> IncludeExplanations(out Explanations explanations);
// Use this overload when querying a Map-Reduce index
IDocumentQuery<T> IncludeExplanations(ExplanationOptions options, out Explanations explanations);
Parameter | Type | Description |
---|---|---|
explanations | Explanations |
An out param that will be filled with the explanations results. |
options | ExplanationOptions |
An object that specifies the GroupKey when querying a Map-Reduce index. |
public class Explanations
{
// Returns a list with all explanations.
// Pass the document ID of a document from the results to get its score details (Map index)
// Pass the GroupKey of an item from the results to get its score details (Map-Reduce index)
public string[] GetExplanations(string key);
}
public sealed class ExplanationOptions
{
// The group key that was used to group by the items in the Map-Reduce index
public string GroupKey { get; set; }
}