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.
class Products_ByCategoryName extends AbstractIndexCreationTask {
constructor() {
super();
this.map = `docs.Products.Select(product => new {
CategoryName = (this.LoadDocument(product.Category, "Categories")).Name
})`;
}
}
const indexDefinition = new IndexDefinition();
indexDefinition.name = "Products/ByCategoryName";
indexDefinition.maps = new Set([
`from product in products
select new {
CategoryName = LoadDocument(product.Category, ""Categories"").name
}`]);
await store.maintenance.send(new PutIndexesOperation(indexDefinition));
Now we will be able to search for products using the categoryName
as a parameter:
const results = session
.query({ indexName: "Products/ByCategoryName" })
.whereEquals("CategoryName", "Beverages")
.ofType(Product)
.all();
Example II
Our next scenario will show us how indexing of more complex relationships is also trivial. Let's consider the following case:
class Book {
constructor(id, name) {
this.id = id;
this.name = name;
}
}
class Author {
constructor(id, name, bookIds) {
this.id = id;
this.name = name;
this.bookIds = bookIds;
}
}
To create an index with Author Name
and list of Book Names
, we need do the following:
class Authors_ByNameAndBooks extends AbstractIndexCreationTask {
constructor() {
super();
this.map = `docs.Authors.Select(author => new {
name = author.name,
books = author.bookIds.Select(x => (this.LoadDocument(x, "Books")).name)
})`;
}
}
const indexDefinition = new IndexDefinition();
indexDefinition.name = "Authors/ByNameAndBooks";
indexDefinition.maps = new Set([
`from author in docs.Authors
select new
{
name = author.name,
books = author.bookIds.Select(x => LoadDocument(x, ""Books"").id)
}`
]);
await store.maintenance.send(new PutIndexesOperation(indexDefinition));
const results = await session
.query({ indexName: "Authors/ByNameAndBooks" })
.whereEquals("name", "Andrzej Sapkowski")
.whereEquals("books", "The Witcher")
.ofType(Author)
.all();
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.