Mapreduce RavenDb—在Reduce函数中聚合的字段上的查询

Mapreduce RavenDb—在Reduce函数中聚合的字段上的查询,mapreduce,ravendb,Mapreduce,Ravendb,我有一组表示一些工作项的文档: 公共类工作项 { 公共字符串Id{get;set; 公共字符串DocumentId{get;set;} 公共字符串字段ID{get;set;} 公共bool已验证{get;set;} } 公共类提取用户 { 公共字符串Id{get;set;} 公共字符串名称{get;set;} 公共字符串[]AssignedFields{get;set;} } 用户可以访问一组字段ID。我需要根据这组字段查询工作项,并获得每个文档的状态: 公共类用户工作项 { 公共字符串Doc

我有一组表示一些工作项的文档:

公共类工作项
{
公共字符串Id{get;set;
公共字符串DocumentId{get;set;}
公共字符串字段ID{get;set;}
公共bool已验证{get;set;}
}
公共类提取用户
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
公共字符串[]AssignedFields{get;set;}
}
用户可以访问一组字段ID。我需要根据这组字段查询工作项,并获得每个文档的状态:

公共类用户工作项
{
公共字符串DocumentId{get;set;}
公共int验证{get;set;}
公共整数总计{get;set;}
}
我要问的问题是:

使用(var session=RavenDb.OpenSession())
{
字符串[]userFields=session.Load(“users/1”).Fields;
session.Query()
.Where(w=>w.FieldId.In(userFields))
.GroupBy(w=>w.DocumentId)
.选择(g=>new
{
DocumentId=g.键,
已验证=g.Where(w=>w.IsValidated).Count(),
总计=总计数()
}).跳过(每页*页).接受(每页)
.ToArray();
}
我曾尝试创建一个Map/Reduce索引,但主要问题是我需要能够对FieldId应用一个过滤器,该过滤器不包括在Reduce输出中,因为它是被计数的属性

我还尝试在查询部分的FieldId上做一个简单的映射索引,并使用TransformResults执行GroupBy,但由于分页是在TransformResults之前应用的,因此页面和总计反映了分组之前的文档,这是不好的

然后,我尝试使用一个多映射索引来映射用户及其字段集合,也映射工作项和字段,然后尝试将结果缩减为我想要的结果。我使用索引定义创建了该索引。缩减部分包括按字段分组,然后多个SelectMany和最后一个GroupBy和Select。该索引已被接受raven,但我没有返回任何结果。我被多重映射索引卡住了,因为我不知道如何调试它

我想最终我的问题可以归结为(双关语)如何在“简化”字段上查询

有什么想法可以实现这样的功能吗?除了Map/MultiMap/Reduce/TransformResults之外,还有什么其他的选择吗

更新:在阅读时,我意识到我接近mapreduce是错误的。仍在寻找解决方案

更新2:经过进一步研究,我最终得到了这个索引,它看起来像我想要做的,但不返回任何数据(该索引是在studio中直接定义的):

地图:

来自文档中的用户
其中用户[“@metadata”][“Raven实体名称”]=“ExtractionUsers”
来自user.AssignedFields中的字段
来自文档中的项目
其中item[“@metadata”][“Raven实体名称”]=“WorkItems”&&item.FieldId==字段
选择新的{
UserId=user.Id,
DocumentId=item.DocumentId,
已验证=项目。状态=“已验证”?1:0,
计数=1
}
减少:

结果中来自r的

按新的{r.UserId,r.DocumentId}将r分组到g中
选择新的{
UserId=g.Key.UserId,
DocumentId=g.Key.DocumentId,
已验证=g.Sum(d=>d.Validated),
Count=g.Sum(d=>d.Count),
}

其想法是尝试将所有文档映射到索引中,并将用户链接到字段和工作项。

首先,免责声明:我以前从未在实际系统中使用过RavenDB,但我阅读了一些文章,观看了一些视频,非常喜欢它背后的想法。我认为这个问题是一个有趣的练习。因此,这是一种可能并不理想的方法;欢迎评论和改进

我的想法是,必须在
工作项
集合上创建索引,以包含以下字段:

  • DocumentId
    (因为这就是我们最后要分组的内容)
  • FieldId
    (因为我们将根据该字段进行筛选)
  • ValidatedCount
    (已验证
    的记录的计数
    =true)
  • TotalCount
创建此索引后,我们可以使用
.Where(x=>x.FieldId.In(userFields))
过滤器查询它,并返回一组具有上述结构的结果

为了得到最终结果,我们需要对这些结果执行更多的分组
DocumentId

我想到的代码是:

索引定义
公共类工作项验证统计:
AbstractIndexCreationTask
{
公共类ReduceResult
{
公共字符串DocumentId{get;set;}
公共字符串字段ID{get;set;}
public int ValidatedCount{get;set;}
公共整数TotalCount{get;set;}
}
公共工作项目验证统计()
{
映射=工作项=>
从workItem到workItems
选择新的
{
workItem.DocumentId,
workItem.FieldId,
ValidatedCount=workItem.IsValidated?1:0,
TotalCount=1
};
减少=结果=>
从结果到结果
按新的{result.FieldId,result.DocumentId}对结果进行分组
进入g
选择新的
{
g、 Key.DocumentId,
g、 Key.FieldId,
ValidatedCount=g.Sum(x=>x.ValidatedCount),
TotalCount=g.Sum(x=>x.TotalCount)
};
}
}
在数据库中创建索引的代码:
public void CreateIndex()
{
使用(var store=CreateDocumentStore())
{
索引创建