Last active
March 10, 2016 17:26
-
-
Save jokokko/fa0edf4673dbd43d5fb1 to your computer and use it in GitHub Desktop.
Marten / Projecting documents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ProjectionSource | |
{ | |
public Guid Id = Guid.NewGuid(); | |
public string Value { get; set; } | |
public int AnotherValue { get; set; } | |
public object ThirdValue { get; set; } | |
} | |
public class ProjectionTarget | |
{ | |
public string Value { get; set; } | |
public object ThirdValue { get; set; } | |
} | |
public class project_document_Tests : DocumentSessionFixture<NulloIdentityMap> | |
{ | |
[Fact] | |
public void project_a_persisted_document() | |
{ | |
var projectionSource = new ProjectionSource() {Value = "Value", AnotherValue = int.MaxValue, ThirdValue = DateTime.UtcNow }; | |
theSession.Store(projectionSource); | |
theSession.SaveChanges(); | |
var projection = ProjectionBuilder<ProjectionSource>.Project().Include(i => i.Value).Include(i => i.ThirdValue).To<ProjectionTarget>(); | |
var projectedValue = theContainer.GetInstance<IDocumentStore>().Project(projectionSource.Id, projection); | |
Assert.Equal(projectionSource.Value, projectedValue.Value); | |
Assert.Equal(projectionSource.ThirdValue, projectedValue.ThirdValue); | |
} | |
} | |
public static class QuerySessionExtensions | |
{ | |
public static TProjection Project<TSource, TProjection>(this IDocumentStore store, object id, Projection<TSource, TProjection> projection) where TSource : class where TProjection : class | |
{ | |
using (var session = store.QuerySession()) | |
{ | |
var mapping = store.Schema.MappingFor(typeof (TSource)); | |
var jsonSelectors = string.Join(",", projection.PropertiesToInclude.Select(x => $"'{x}',{mapping.TableName}.data->'{x}'")); | |
var projectionQuery = session.Connection.CreateCommand($"select json_build_object({ jsonSelectors }) from { mapping.TableName } where id = :id").With("id", id); | |
using (var reader = projectionQuery.ExecuteReader()) | |
{ | |
var found = reader.Read(); | |
return found ? store.Advanced.Options.Serializer().FromJson<TProjection>(reader.GetString(0)) : null; | |
} | |
} | |
} | |
} | |
public class Projection<TSource, TProjection> | |
{ | |
public readonly IEnumerable<string> PropertiesToInclude; | |
public Projection(IEnumerable<string> propertiesToInclude) | |
{ | |
PropertiesToInclude = propertiesToInclude; | |
} | |
} | |
public class ProjectionBuilder<TSource> | |
{ | |
private readonly IEnumerable<string> propertiesToInclude; | |
private ProjectionBuilder() | |
{ | |
propertiesToInclude = Enumerable.Empty<string>(); | |
} | |
public ProjectionBuilder(IEnumerable<string> propertiesToInclude) | |
{ | |
this.propertiesToInclude = propertiesToInclude; | |
} | |
public static ProjectionBuilder<TSource> Project() | |
{ | |
return new ProjectionBuilder<TSource>(); | |
} | |
public ProjectionBuilder<TSource> Include(Expression<Func<TSource, object>> field) | |
{ | |
var expression = (MemberExpression)field.Body; | |
var name = expression.Member.Name; | |
return new ProjectionBuilder<TSource>(propertiesToInclude.Concat(new[] { name })); | |
} | |
public Projection<TSource, TProjection> To<TProjection>() | |
{ | |
return new Projection<TSource, TProjection>(propertiesToInclude); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment