如何在Ravendb中反向索引相关文档 [英] How to index related documents in reverse direction in Ravendb
问题描述
在
In Example II of Indexing Related Documents, an index is built over Authors by Name and Book title. The relevant entities look like so:
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; }
}
即仅Author
保存有关该关系的信息.该信息用于构建所述索引.
I.e. only the Author
holds information about the relation. This information is used in constructing said index.
但是我将如何基于作者的书籍构建索引(假设一本书可以有多位作者)?
But how would I construct an index over Books by Authors (assuming a book could have multiple authors)?
这本书/作者的类推仅到目前为止.我将举一个更接近实际用例的示例:
The book/author analogy only goes so far. I'll make an example that's closer to my actual use case:
假设我们有一些与位置相关的任务:
Suppose we have some tasks that are tied to locations:
public class Location {
public string Id { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class Task {
public string Id { get; set; }
public string Name { get; set; }
public string LocationId { get; set; }
public Status TaskStatus { get; set; }
}
我有一个端点,将Locations作为GeoJson用作客户端中的地图视图.我想根据与位置相关联的任务的状态为位置着色.该地图通常会显示500-2000个位置.
I have an endpoint serving Locations as GeoJson to a map view in a client. I want to color the Locations depending on status of Tasks associated with them. The map would typically show 500-2000 locations.
关于位置的查询被实现为流查询.
The query on locations is implemented as a streaming query.
使用Ayende最初回答中指出的查询方法,我可能会做类似的事情:
Using the query-method indicated in Ayende's initial answer, I might do something like:
foreach (var location in locationsInView)
{
var completedTaskIds = await RavenSession.Query<Task>()
.Where(t => t.LocationId == location.Id && t.TaskStatus == Status.Completed)
.ToListAsync();
//
// Construct geoJson from location and completedTaskIds
//
}
这导致针对RavenDB执行500-2000个查询,这似乎不正确. 这就是为什么我最初认为我需要一个索引来构造结果的原因.
This results in 500-2000 queries being executed against RavenDB, which doesn't seem right. This is why I initially thought I needed an index to construct my result.
此后,我了解到RavenDB默认情况下会缓存所有内容,因此这可能不是问题.另一方面,实施此方法后,出现错误("...此会话允许的最大请求数(30)...").
I have since read that RavenDB caches everything by default, so that might be a non-issue. On the other hand, having implemented this approach, I get an error ("...maximum number of requests (30) allowed for this session...").
什么是解决此问题的好方法?
What is a good way of fixing this?
推荐答案
您可以使用多重地图/缩小索引.
所有有关关注对象的事实真相都映射到通用对象类型(Result
).然后,通过ID减少此映射的分组,并仅保留相关部分,从而创建有关每个对象的真相的合并"(在本例中为Book
).因此,以Book/Author示例为例,其中可能有几位Authors对同一本书做出了贡献,您可以执行以下操作.
All sources of truth about the objects of interest are mapped to a common object type (Result
). This mapping is then reduced grouping by Id and keeping just the relevant pieces, creating a "merge" of truths about each object (Book
in this case). So using the Book/Author example, where several Authors might have contributed to the same book, you could do something like the following.
请注意,映射和归约步骤必须输出相同类型的对象,这就是在从作者进行映射的过程中将author.Id包裹在列表中的原因.
Note that the map and reduce steps must output the same type of object, which is why author.Id is wrapped in a list during the mapping from author.
Author.Name
不包括在内,但可以与Author.Id
完全相同的方式包括在内.
Author.Name
s are excluded for brevity, but could be included in the exact same way as Author.Id
.
public class BooksWithAuthors : AbstractMultiMapIndexCreationTask<BooksWithAuthors.Result>
{
public class Result
{
string Id;
string Title;
IEnumerable<string> AuthorIds;
}
public BooksWithAuthors()
{
AddMap<Book>(book => from book in books
select new
{
Id = book.Id,
Title = book.Title,
AuthorIds = null;
});
AddMap<Author>(author => from author in authors
from bookId in author.bookIds
select new
{
Id = bookId,
Title = null,
AuthorIds = new List<string>(){ author.Id };
});
Reduce = results => from result in results
group result by result.Id
into g
select new
{
Id = g.Key,
Title = g.Select(r => r.Title).Where(t => t != null).First(),
AuthorIds = g.Where(r => r.AuthorIds != null).SelectMany(r => r.AuthorIds)
};
}
}
这篇关于如何在Ravendb中反向索引相关文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!