如何在 RavenDB 中创建具有多个分组的 map/reduce 索引

How do you create a map/reduce index with multiple groupings in RavenDB

我们正在 Raven 中存储一组文档。

public class MyDocument
{
  public string Id { get; set; }
  public string DocumentType { get; set; }
  public int ClientId { get; set; }
  public string Status { get; set; }
}

我们想要显示按 ClientId 和 DocumentType 分组的文档报告,如下所示:

DocumentType ClientHasManyOfThese 计数操作
------------------------------------------------------ ----------
DocumentType1 是 10 LinkToListOfDocuments
DocumentType1 否 5 LinkToListOfDocuments
DocumentType2 是 12 LinkToListOfDocuments
DocumentType2 否 15 LinkToListOfDocuments

我创建了以下索引,但它只为少量文档返回正确的结果。

public class MyDocumentCount
{
  public string DocumentType { get; set; }
  public int ClientId { get; set; }
  public int Count { get; set; }
  public bool MultipleDocumentsForClient { get; set; }
}

public class MyIndex : AbstractIndexCreationTask<MyDocument, MyDocumentCount>
{
  public MyIndex()
  {
    Map = tasks => 
      from task in tasks
      where task.Status = "Show In Report"
      select new MyDocumentCount
      {
        DocumentType = task.DocumentType,
        ClientId = task.ClientId,
        MultipleDocumentsForClient = false,
        Count = 1
      };

    Reduce = results =>
      results.GroupBy(result => new 
      {
        result.DocumentType, 
        result.ClientId
      }).Select(conDocGrp => new MyDocumentCount 
      {
        DocumentType = conDocGrp.Key.DocumentType,
        Count = conDocGrp.Sum(result => result.Count),
        MultipleDocumentsForClient = conDocGrp.Sum(result => result.Count) > 1,
        ClientId = conDocGrp.Key.ClientId
      });

    TransformResults = (database, results) =>
      results.GroupBy(result => new
      {
        result.DocumentType,
        result.MultipleDocumentsForClient
      }).Select(multDocGrp => new
      {
        multDocGrp.Key.DocumentType,
        multDocGrp.Key.MultipleDocumentsForClient,
        Count = multDocGrp.Sum(result => int.Parse(result.Count.ToString(CultureInfo.InvariantCulture))),
        ClientId = 0
      });
  }
}

我认为这与调用时Raven中的结果计数限制有关:

var results = session.Query<MyDocumentCount, MyIndex>().ToList();

可能在执行转换之前将限制应用于索引结果?

谁能告诉我我做错了什么,是否有办法实现我想要的?

我们目前 运行 RavenDB (Server Build 2380)。

谢谢。

所以从我能收集到的问题的基本要点是,你正在尝试聚合一个聚合。具体来说,您尝试按 ClientIdDocumentType 进行分组,然后尝试按 MultipleDocumentsForClient 汇总这些结果。您的索引适用于大多数情况,但是当 Reduce 产生的结果超过默认的 RavenDB 'page size' 限制时,您将无法获得所需的输出。

我确认 TransformResults 最多只能从 RavenDB 接收页面限制大小。您可以将 TransformResults 视为在客户端执行,以确保您以后不会犯任何错误。也许这就是它被弃用的原因,我们应该改用变形金刚。

为了立即解决您的问题,我认为您在一个索引中做的太多了。转换器部分并不是真正用于转换查询结果,而是用于再次聚合。 如果你不能在索引的 Reduce 部分做所有的聚合,那么我建议你尝试将索引拆分成两个更小的索引。也许在这种情况下,一个索引可以用于客户端有多个文档的情况,一个可以用于客户端只有一个文档的情况。然后您必须将两个结果都加载到内存中,这似乎适合您的情况,因为您已经在查询中使用了 .ToList