如何在 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)。
谢谢。
所以从我能收集到的问题的基本要点是,你正在尝试聚合一个聚合。具体来说,您尝试按 ClientId
和 DocumentType
进行分组,然后尝试按 MultipleDocumentsForClient
汇总这些结果。您的索引适用于大多数情况,但是当 Reduce 产生的结果超过默认的 RavenDB 'page size' 限制时,您将无法获得所需的输出。
我确认 TransformResults
最多只能从 RavenDB 接收页面限制大小。您可以将 TransformResults
视为在客户端执行,以确保您以后不会犯任何错误。也许这就是它被弃用的原因,我们应该改用变形金刚。
为了立即解决您的问题,我认为您在一个索引中做的太多了。转换器部分并不是真正用于转换查询结果,而是用于再次聚合。
如果你不能在索引的 Reduce 部分做所有的聚合,那么我建议你尝试将索引拆分成两个更小的索引。也许在这种情况下,一个索引可以用于客户端有多个文档的情况,一个可以用于客户端只有一个文档的情况。然后您必须将两个结果都加载到内存中,这似乎适合您的情况,因为您已经在查询中使用了 .ToList
。
我们正在 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)。
谢谢。
所以从我能收集到的问题的基本要点是,你正在尝试聚合一个聚合。具体来说,您尝试按 ClientId
和 DocumentType
进行分组,然后尝试按 MultipleDocumentsForClient
汇总这些结果。您的索引适用于大多数情况,但是当 Reduce 产生的结果超过默认的 RavenDB 'page size' 限制时,您将无法获得所需的输出。
我确认 TransformResults
最多只能从 RavenDB 接收页面限制大小。您可以将 TransformResults
视为在客户端执行,以确保您以后不会犯任何错误。也许这就是它被弃用的原因,我们应该改用变形金刚。
为了立即解决您的问题,我认为您在一个索引中做的太多了。转换器部分并不是真正用于转换查询结果,而是用于再次聚合。
如果你不能在索引的 Reduce 部分做所有的聚合,那么我建议你尝试将索引拆分成两个更小的索引。也许在这种情况下,一个索引可以用于客户端有多个文档的情况,一个可以用于客户端只有一个文档的情况。然后您必须将两个结果都加载到内存中,这似乎适合您的情况,因为您已经在查询中使用了 .ToList
。