Skip to content

Instantly share code, notes, and snippets.

@etishor
Created November 7, 2012 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save etishor/4031390 to your computer and use it in GitHub Desktop.
Save etishor/4031390 to your computer and use it in GitHub Desktop.
Multi map reduce index
using System;
using System.Linq;
using Raven.Client;
using Raven.Client.Document;
using Raven.Client.Indexes;
namespace RavenTest
{
public class ExtractionUser
{
public string Id { get; set; }
public string[] AssignedFields { get; set; }
}
public class WorkItem
{
public string Id { get; set; }
public string DocumentId { get; set; }
public string FieldId { get; set; }
public string Status { get; set; }
}
public class UserWorkItem : AbstractMultiMapIndexCreationTask<UserWorkItem.Result>
{
public class Result
{
public string FieldId { get; set; }
public string UserId { get; set; }
public string DocumentId { get; set; }
public int Count { get; set; }
public int Validated { get; set; }
}
public UserWorkItem()
{
AddMap<ExtractionUser>(users => users.SelectMany(u => u.AssignedFields, (user, fied) => new
{
FieldId = fied,
UserId = user.Id,
DocumentId = (string)null,
Count = 0,
Validated = 0
}));
AddMap<WorkItem>(items => items.Select(item => new
{
FieldId = item.FieldId,
UserId = (string)null,
DocumentId = item.DocumentId,
Count = 1,
Validated = item.Status == "Validated" ? 1 : 0
}));
Reduce = results => results.GroupBy(r => r.FieldId)
// gather all the users and all the documents with a common field
.Select(g => new
{
FieldId = g.Key,
Users = g.Where(u => u.UserId != null)
.Select(d => d.UserId)
.DefaultIfEmpty(),
Documents = g.Where(d => d.DocumentId != null)
.Select(d => new
{
DocumentId = d.DocumentId,
Count = d.Count,
Validated = d.Validated
}).DefaultIfEmpty(new
{
DocumentId = (string)null,
Count = 0,
Validated = 0
})
})
// make all combinations of field , user , document by .SelectMany first on Users then on Documents
.SelectMany(d => d.Users, (d, user) => new
{
FieldId = d.FieldId,
UserId = user,
Documents = d.Documents,
})
.SelectMany(d => d.Documents, (d, document) => new
{
// if we have a value for UserId and for DocumentId then compose a FieldId from these values else use the initial FieldId
FieldId = (d.UserId != null && document.DocumentId != null) ?
d.UserId + " " + document.DocumentId : d.FieldId,
UserId = d.UserId,
DocumentId = document.DocumentId,
Count = document.Count,
Validated = document.Validated
})
// aggregate the final result
.GroupBy(d => new { d.FieldId, d.UserId, d.DocumentId })
.Select(g => new
{
FieldId = g.Key.FieldId,
UserId = g.Key.UserId,
DocumentId = g.Key.DocumentId,
Count = g.Sum(d => d.Count),
Validated = g.Sum(d => d.Validated)
});
}
}
class Program
{
static void Main(string[] args)
{
//using (EmbeddableDocumentStore store = new EmbeddableDocumentStore { RunInMemory = true })
using (DocumentStore store = new DocumentStore { ConnectionStringName = "RavenDb" })
{
store.Initialize();
IndexCreation.CreateIndexes(typeof(UserWorkItem).Assembly, store);
//using (var session = store.OpenSession())
//{
// CreateDocs(session);
// session.SaveChanges();
//}
//using (var session = store.OpenSession())
//{
// var result = session.Query<WorkItem, UserWorkItem>()
// .Customize(q => q.WaitForNonStaleResults())
// .As<UserWorkItem.Result>()
// .ToArray();
//}
}
Console.WriteLine("Done");
Console.ReadKey();
}
private static void CreateDocs(IDocumentSession session)
{
//ExtractionUser u1 = new ExtractionUser { Id = "ExtractionUsers/1", AssignedFields = new string[] { "field1", "field2" } };
//ExtractionUser u2 = new ExtractionUser { Id = "ExtractionUsers/2", AssignedFields = new string[] { "field1", "field3" } };
//ExtractionUser u3 = new ExtractionUser { Id = "ExtractionUsers/3", AssignedFields = new string[] { "field1", "field4" } };
//WorkItem wi1 = new WorkItem { DocumentId = "documents/1", FieldId = "field1", Status = "Ready" };
//WorkItem wi2 = new WorkItem { DocumentId = "documents/1", FieldId = "field2", Status = "Ready" };
//WorkItem wi3 = new WorkItem { DocumentId = "documents/1", FieldId = "field3", Status = "Ready" };
//WorkItem wi4 = new WorkItem { DocumentId = "documents/1", FieldId = "field4", Status = "Ready" };
//WorkItem wi5 = new WorkItem { DocumentId = "documents/2", FieldId = "field1", Status = "Ready" };
//WorkItem wi6 = new WorkItem { DocumentId = "documents/2", FieldId = "field2", Status = "Ready" };
//WorkItem wi7 = new WorkItem { DocumentId = "documents/2", FieldId = "field3", Status = "Ready" };
//WorkItem wi8 = new WorkItem { DocumentId = "documents/2", FieldId = "field4", Status = "Ready" };
//WorkItem wi9 = new WorkItem { DocumentId = "documents/3", FieldId = "field4", Status = "Ready" };
//session.Store(wi9);
//session.Store(u1);
//session.Store(u2);
//session.Store(u3);
//session.Store(wi1);
//session.Store(wi2);
//session.Store(wi3);
//session.Store(wi4);
//session.Store(wi5);
//session.Store(wi6);
//session.Store(wi7);
//session.Store(wi8);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment