3

我知道includeRavenDB 的 -feature。它允许我在一次往返数据库的过程中立即获取引用的文档。但我的问题是:我首先获取的文档不包括对“其他”文档的引用。但是“其他”文件引用了当前文件。

想象一下我们在世界各地都有站点的设置。每个都site可能触发各种警报。每个alarm都有对sitevia的引用siteId

现在我想获取所有站点的列表,包括所有警报。但看起来,这对 RavenDB 来说是不可能的吗?因为include只接受site-Document 中的“路径”,该路径包含引用文档的 id(或 id 数组)。

这可以通过在包含订单lineItems站点alarmIds内提供一个数组来解决,该站点将运行多年,收集 0 到 100 万之间的警报。这对我来说似乎是个坏主意。site'-document and referencing this array in . But in contrast to a lot of examples featuring stuff like an withwhere the order is a self contained thing, my

当然我也可以反过来:include通过 查询所有警报和站点sitesId。但这不会返回警报为零的站点。

那么这只是我这边的一个设计错误吗?我误解了什么?还是不可能在一个查询中执行此操作并防止“n+1 查询”?

4

2 回答 2

3
public class A
{
    public string Id { get; set; }
}

public class B
{
    public string Id { get; set; }
    public string A { get; set; }
}

public class MultiMapIndex : AbstractMultiMapIndexCreationTask<MultiMapIndex.Result>
{
    public class Result
    {
        public string Id { get; set; }
        public IEnumerable<string> Bs { get; set; }
    }

    public MultiMapIndex()
    {
        AddMap<A>(items => from a in items
            select new Result {Id = a.Id, Bs = new string[0]});

        AddMap<B>(items => from b in items
            select new Result {Id = b.A, Bs = new[] {b.Id}});

        Reduce = results => from result in results
            group result by result.Id
            into g
            select new Result {Id = g.Key, Bs = g.SelectMany(r => r.Bs)};
    }
}

[Fact]
public async Task TestCase()
{
    using var store = GetDocumentStore();

    await new MultiMapIndex().ExecuteAsync(store);
    using (var session = store.OpenAsyncSession())
    {
        await session.StoreAsync(new B {A = "a/1"}, "b/0");
        await session.StoreAsync(new A(), "a/1");
        await session.StoreAsync(new A(), "a/2");
        await session.SaveChangesAsync();
    }

    WaitForIndexing(store);

    using (var session = store.OpenAsyncSession())
    {
        var results = await session.Query<MultiMapIndex.Result, MultiMapIndex>()
            .Include(r => r.Bs)
            .ToArrayAsync();

        var before = session.Advanced.NumberOfRequests;

        var bs = session.LoadAsync<B>(results[0].Bs);

        Assert.Equal(before, session.Advanced.NumberOfRequests);
    }
}
于 2021-10-24T12:39:21.970 回答
2

如果您确实选择查询 all Alarms,正如您所提到的,
那么您可以在警报集合上创建一个Map-Reduce 索引,该索引将按站点分组。
然后,您可以查询此Map-Reduce 索引并了解每个站点它具有或不具有的警报计数...

https://demo.ravendb.net/demos/csharp/static-indexes/map-reduce-index

于 2021-10-21T17:15:29.220 回答