将映射/还原索引的结果提供给另一个索引以进行进一步缩减

本文关键字:索引 另一个 进一步 映射 还原 结果 | 更新日期: 2023-09-27 18:35:36

我有一个集合,我需要确定值的总运行总和。文档如下所示(大量简化和匿名化):

public class Entry
{
    public string id {get;set;}
    public string CompanyId {get;set;}
    public string CustomerId {get;set;}
    public decimal PurchaseAmount {get;set;}
    public bool VoidAllEntries {get;set;}
    public DateTime CreatedOn {get;set;}
    // and many others that are irrelevant to this question
}

我制作了一个 Map/Reduce 索引,试图将值分解为分组,按 CompanyIdCustomerId 分组。我有兴趣从每个组中获取最新的Entry(基于CreatedOn),然后将所有内容归结为PurchaseAmount总数。我需要它以这种方式工作的原因是,如果最新EntryVoidAllEntries属性为真,我不需要将PurchaseAmount计入总计。因此,索引结果如下所示:

public class SummaryResult
{
    public string CompanyId {get;set;}
    public string CustomerId {get;set;}
    public decimal PurchaseAmount {get;set;}
    public bool VoidAllEntries {get;set;}
    public DateTime CreatedOn {get;set;}
} 

我当前的映射/还原索引方法如下所示:

// Let's call it SummaryIndex
Map = list => from val in list
              select new
              {
                  val.CompanyId,
                  val.CustomerId,
                  val.VoidAllEntries,
                  PurchaseAmount = val.VoidAllEntries ? 0 : val.PurchaseAmt + val.OtherCosts,
                  val.CreatedOn
               };
Reduce = results => from r in results
                    orderby r.CreatedOn
                    group r by new { r.CompanyId, r.CustomerId }
                    into g
                    let latest = g.OrderByDescending(x => x.CreatedOn).First()
                    select new
                    {
                        g.Key.CompanyId,
                        g.Key.CustomerId,
                        latest.VoidAllEntries,
                        latest.CreatedOn,
                        latest.PurchaseAmount
                    };

这实际上可以很好地分组和获取最新Entry。现在我面临的问题是,我似乎无法弄清楚如何根据这些结果让 RavenDB 在服务器上执行第二个 Map/Reduce 操作。最后,我希望能够将其缩小到3件事:

public class FinalResult 
{
    public string CompanyId {get;set;}
    public decimal PurchaseGrandTotal {get;set;}
    public decimal Count {get;set;} 
}

PurchaseGrandTotalCount相当于我在客户端上运行它:

var results = session.Query<SummaryResult, SummaryIndex>()
    .Where(x => x.CompanyId == "companies/1")
    .ToList();
var grandTotal = results.Sum(x => x.PurchaseAmount);
var count = results.Count;

我想在服务器上执行此操作的原因是因为我可能要处理大量数据,并且我不想仅仅为了处理这些摘要而必须在客户端上加载所有内容。我不知道我是否可以在 C# 中制作第二个 Map/Reduce 索引,它将 SummaryIndex 的结果作为输入。

有什么想法吗?我这样做的方式是错误的吗?

编辑:我不得不改写这个问题,因为从技术上讲,Ayende下面的答案是我最初措辞的问题的正确答案。但是,我在凌晨 2 点发布了它,我想我没有正确解释我的问题。我不能使用脚本索引的原因是结果没有存储为文档(这是我让 Ayende 相信的)。除了脚本索引,还有其他方法吗?现在我只是使用流式处理来手动计算客户端上的记录,并且工作正常,但我想确保没有其他选择。

将映射/还原索引的结果提供给另一个索引以进行进一步缩减

脚本

化索引结果支持此功能。查看文档

http://ravendb.net/docs/article-page/3.0/Csharp/server/bundles/scripted-index-results