如何在Ravendb中反向索引相关文档

在索引相关文档的示例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 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() .Where(t => t.LocationId == location.Id && t.TaskStatus == Status.Completed) .ToListAsync(); // // Construct geoJson from location and completedTaskIds // } 

这导致对RavenDB执行500-2000个查询,这似乎不对。 这就是为什么我最初认为我需要一个索引来构造我的结果。

我已经读过RavenDB默认缓存所有内容,所以这可能不是问题。 另一方面,实施这种方法后,我收到一个错误(“……此会话允许的最大请求数(30)……”)。

解决这个问题的好方法是什么?

您无法以这种方式索引它们。 但你也不需要。

如果您想查找作者的所有书籍,请加载作者并获得完整列表。

您可以使用多地图/缩小索引执行此操作。

关于感兴趣对象的所有真实来源都被映射到一个共同的对象类型( Result )。 然后,这个映射通过Id减少分组,并保留相关的部分,创建关于每个对象的真实的“合并”(在本例中为Book )。 因此,使用书籍/作者示例,其中几位作者可能对同一本书做出了贡献,您可以执行以下操作。

请注意,map和reduce步骤必须输出相同类型的对象,这就是author.Id在作者映射期间包装在列表中的原因。

为简洁起见,排除了Author.Name ,但可以与Author.Id完全相同的方式Author.Id

 public class BooksWithAuthors : AbstractMultiMapIndexCreationTask { public class Result { string Id; string Title; IEnumerable AuthorIds; } public BooksWithAuthors() { AddMap(book => from book in books select new { Id = book.Id, Title = book.Title, AuthorIds = null; }); AddMap(author => from author in authors from bookId in author.bookIds select new { Id = bookId, Title = null, AuthorIds = new List(){ 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) }; } }