I have a set of documents that are some work items:
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;} }
The user has access to the FieldIds set. I need to query WorkItems based on this set of fields and get the status for each document:
public class UserWorkItems { public string DocumentId { get; set; } public int Validated { get; set; } public int Total { get; set; } }
The next request is the following:
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(); }
I tried to create a Map / Reduce index, but the main problem was that I needed to apply a filter to FieldId, which is not included in the Reduce output stream, since it is a counted property.
I also tried to make a simple Map index in FieldId for the query part and TransformResults to execute GroupBy, but since paging is applied before TransformResults, the pages and totals reflect the documents before grouping, which is not very good.
Then I tried to use the Multi Map index, which displays users and their collection of fields, and also displays work items and a field, and then tries to reduce the result to what I wanted. I created a gist with an index definition. Part of the abbreviation includes a group by field, followed by several SelectMany and final GroupBy and Select. The index was adopted by the raven, but I will not return any results. Iโm a bit stuck in the Multi Map index, because I donโt know how I could debug it.
I assume that eventually my problem can be reduced (pun intended) before requesting a โreducedโ field?
Any ideas how I could achieve such functionality? Are there any other features that I could explore next to Map / MultiMap / Reduce / TransformResults?
UPDATE : while reading Ayende Map Shorten message I realized that I am approaching the wrong picture. Still looking for a solution ...
UPDATE 2 : after a bit more research, I ended up with this index, which looks the way I want, but returns no data (the index was defined directly in the studio)
Map
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 }
Decrease:
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), }
The idea is to try to map all documents and a link from users to fields and WorkItems in the index.