如何在Ravendb中反向索引相关文档 [英] How to index related documents in reverse direction in Ravendb

查看:111
本文介绍了如何在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.Names 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆