【发布时间】:2012-11-06 11:04:17
【问题描述】:
我有一组代表一些工作项的文档:
public class WorkItem
{
public string Id {get;set;
public string DocumentId { get; set; }
public string FieldId { get; set; }
public bool IsValidated { get; set; }
}
public class ExtractionUser
{
public string Id {get;set;}
public string Name {get;set;}
public string[] AssignedFields {get;set;}
}
用户有权访问一组 FieldId。我需要根据这组字段查询 WorkItems 并获取每个文档的状态:
public class UserWorkItems
{
public string DocumentId { get; set; }
public int Validated { get; set; }
public int Total { get; set; }
}
我的查询是这样的:
using (var session = RavenDb.OpenSession())
{
string[] userFields = session.Load<User>("users/1").Fields;
session.Query<WorkItem>()
.Where(w => w.FieldId.In(userFields))
.GroupBy(w => w.DocumentId)
.Select(g => new
{
DocumentId = g.Key,
Validated = g.Where(w => w.IsValidated).Count(),
Total = g.Count()
}).Skip(page * perPage).Take(perPage)
.ToArray();
}
我已尝试创建 Map/Reduce 索引,但主要问题是我需要能够对未包含在 Reduce 输出中的 FieldId 应用过滤器,因为它是被计算的属性。
我还尝试在查询部分的 FieldId 上创建一个简单的 Map 索引,并使用 TransformResults 来执行 GroupBy - 但由于在 TransformResults 之前应用了分页,因此页面和总计反映了分组之前的文档,这是不好的。
然后我尝试使用 Multi Map 索引来映射用户及其字段集合,并映射工作项和字段,然后尝试将结果减少到我想要的。我用索引定义创建了a gist。减少部分涉及按字段分组,然后是多个 SelectMany 和最后一个 GroupBy 和 Select。该索引已被 raven 接受,但 i 不返回任何结果。我有点卡在 Multi Map 索引上,因为我不知道如何实际调试它。
我想最后我的问题可能会减少(双关语)如何查询“减少”字段?
有什么想法可以实现这样的功能吗?除了 Map/MultiMap/Reduce/TransformResults 之外,我还有其他选择吗?
更新:在阅读 Ayende's Map Reduce post 时,我意识到我正在接近 mapreduce 错误。仍在寻找解决方案...
更新 2:经过更多研究,我最终得到了这个索引,它看起来像我想要做的,但没有返回任何数据(索引是直接在工作室中定义的) :
地图:
from user in docs
where user["@metadata"]["Raven-Entity-Name"] == "ExtractionUsers"
from field in user.AssignedFields
from item in docs
where item["@metadata"]["Raven-Entity-Name"] == "WorkItems" && item.FieldId == field
select new {
UserId = user.Id,
DocumentId = item.DocumentId,
Validated = item.Status=="Validated"? 1: 0,
Count = 1
}
减少:
from r in results
group r by new { r.UserId , r.DocumentId } into g
select new {
UserId = g.Key.UserId,
DocumentId = g.Key.DocumentId,
Validated = g.Sum(d => d.Validated),
Count = g.Sum(d => d.Count),
}
这个想法是尝试在索引中映射所有文档,并从用户链接到字段和工作项。
【问题讨论】:
-
您能否更详细地描述一下您的结构(
User和Field类)? -
我添加了 User ( ExtractionUser ) 类的结构 - 它只是一个 Id、Name 和 AssignedFields 集合。该字段仅作为字段名称的 Id 存在 - 所以那里没有实际的类。需要考虑的一件事是,AssignedFields 会随着用户获得分配给它们的新字段而及时更改 - 因此非规范化工作项中的信息不是一种选择。
-
您发布的更新索引不起作用,您不能在这样的索引中包含 2 个“from x in docs”。如果您想跨多种类型建立索引,请查看 Multi-Map,ravendb.net/kb/11/…
-
@MattWarren 谢谢,我现在正在尝试使用多映射减少,但减少部分没有返回所有结果。我创建了一个gist here
-
我在mailinglist上发布了更多信息