在Indexing Related Documents的示例II中,按名称和书名在作者上建立索引。相关实体看起来像这样:
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
包含有关该关系的信息。该信息用于构建所述索引。
但是我如何构建一个关于Books by Authors的索引(假设一本书可能有多个作者)?
修改
这本书/作者的比喻只是到目前为止。我将举一个更接近我实际用例的例子:
假设我们有一些与地点相关的任务:
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个位置。
对位置的查询实现为流式查询。
使用Ayende最初答案中指出的查询方法,我可能会这样做:
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个查询,这似乎不对。 这就是为什么我最初认为我需要一个索引来构建我的结果。
我已经读过RavenDB默认缓存所有内容,因此这可能不是问题。另一方面,实施这种方法后,我收到一个错误(“......此会话允许的最大请求数(30)......”)。
解决这个问题的好方法是什么?
答案 0 :(得分:1)
您不能以这种方式索引它们。 但你也不需要。
如果您想查找作者的所有图书,请加载作者并获得完整列表。
答案 1 :(得分:0)
您可以使用multi map/reduce index执行此操作。
关于感兴趣对象的所有真实来源都映射到一个共同的对象类型(Result
)。然后,通过Id减少分组并仅保留相关部分,创建关于每个对象的真实的“合并”(在这种情况下为Book
)。因此,使用书籍/作者示例,其中几位作者可能对同一本书做出了贡献,您可以执行以下操作。
请注意,map和reduce步骤必须输出相同类型的对象,这就是author.Id在作者映射过程中被包装在列表中的原因。
为简洁起见, Author.Name
被排除在外,但可以与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)
};
}
}