Indexes: Indexing Related Documents
To extend indexing capabilities and simplify many scenarios, we have introduced the possibility for indexing related documents.
Example I
Let's consider a simple Product - Category
scenario where you want to look for a Product
by Category Name
.
Without this feature, you would have to create a fairly complex multiple map-reduce index. This is why the LoadDocument
function was introduced.
public class Products_ByCategoryName : AbstractIndexCreationTask<Product>
{
public class Result
{
public string CategoryName { get; set; }
}
public Products_ByCategoryName()
{
Map = products => from product in products
select new
{
CategoryName = LoadDocument<Category>(product.Category).Name
};
}
}
store.Maintenance.Send(new PutIndexesOperation
(
new IndexDefinition
{
Name = "Products/ByCategoryName",
Maps =
{
@"from product in products
select new
{
CategoryName = LoadDocument(product.Category, ""Categories"").Name
}"
}
}
));
Now we will be able to search for products using the CategoryName
as a parameter:
IList<Product> results = session
.Query<Products_ByCategoryName.Result, Products_ByCategoryName>()
.Where(x => x.CategoryName == "Beverages")
.OfType<Product>()
.ToList();
Example II
Our next scenario will show us how indexing of more complex relationships is also trivial. Let's consider the following case:
public class Book
{
public string Id { get; set; }
public string Name { get; set; }
}
public class Author
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> BookIds { get; set; }
}
To create an index with Author Name
and list of Book Names
, we need do the following:
public class Authors_ByNameAndBooks : AbstractIndexCreationTask<Author>
{
public class Result
{
public string Name { get; set; }
public IList<string> Books { get; set; }
}
public Authors_ByNameAndBooks()
{
Map = authors => from author in authors
select new
{
Name = author.Name,
Books = author.BookIds.Select(x => LoadDocument<Book>(x).Name)
};
}
}
store.Maintenance.Send(new PutIndexesOperation
(
new IndexDefinition
{
Name = "Authors/ByNameAndBooks",
Maps =
{
@"from author in docs.Authors
select new
{
Name = author.Name,
Books = author.BookIds.Select(x => LoadDocument(x, ""Books"").Id)
}"
}
}
));
IList<Author> results = session
.Query<Authors_ByNameAndBooks.Result, Authors_ByNameAndBooks>()
.Where(x => x.Name == "Andrzej Sapkowski" || x.Books.Contains("The Witcher"))
.OfType<Author>()
.ToList();
Remarks
Information
Indexes are updated automatically when related documents change.
Warning
Using the LoadDocument
adds a loaded document to the tracking list. This may cause very expensive calculations to occur, especially when multiple documents are tracking the same document.