/// <summary> /// Creates an aggregate hook to lookup some fields before population /// </summary> /// <param name="aggregate">The aggregate to add the stages to</param> /// <param name="t">The type to reference</param> /// <param name="settings">The settings. Please leave empty, used in recursion</param> private void BuildAggregateHook(ref IAggregateFluent <BsonDocument> aggregate, Type t, AggregateSettings settings = null) { settings ??= new AggregateSettings(); foreach (var prop in t.GetProperties()) { Log("[AGG] Property " + settings.GetPath(prop.Name)); foreach (var attr in prop.GetCustomAttributes()) { //If reference attribute, add a lookup for it if (attr is ReferenceAttribute refAttr) { if (_populates.TryGetValue(settings.GetPath(prop.Name), out var isEnabled)) { refAttr.Enabled = isEnabled; } if (!refAttr.Enabled) { break; } Log("[AggR] Enabled reference found"); var localField = settings.GetPath(refAttr.LocalField); var targetField = settings.GetPath(prop.Name); aggregate = aggregate.Lookup(refAttr.RefCollection, localField, refAttr.RefField, targetField); if (!prop.PropertyType.IsCollection(out _)) { aggregate = aggregate.Unwind(targetField); } } //If embed, create aggregate for it if (attr is EmbedAttribute) { if (!settings.DoNest) { return; } bool isCollection = prop.PropertyType.IsCollection(out Type elementType); //If collection, add $unwind if (isCollection) { aggregate = aggregate.Unwind(settings.GetPath(prop.Name)); } //Call build aggregate hook BuildAggregateHook(ref aggregate, elementType, new AggregateSettings { Path = settings.GetPath(prop.Name) + ".", DoNest = false, ParentType = t, IsCollection = isCollection }); AddGroupHook(settings.GetPath(prop.Name), t, ref aggregate); } } } }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TNewResult">The type of the new result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="field">The field to unwind.</param> /// <param name="newResultSerializer">The new result serializer.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TNewResult> Unwind <TResult, TNewResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field, IBsonSerializer <TNewResult> newResultSerializer = null) { Ensure.IsNotNull(aggregate, "aggregate"); Ensure.IsNotNull(field, "field"); return(aggregate.Unwind <TNewResult>(new ExpressionFieldDefinition <TResult>(field), newResultSerializer)); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="field">The field to unwind.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <BsonDocument> Unwind <TResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field) { Ensure.IsNotNull(aggregate, "aggregate"); Ensure.IsNotNull(field, "field"); return(aggregate.Unwind <BsonDocument>(new ExpressionFieldDefinition <TResult>(field))); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="field">The field to unwind.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <BsonDocument> Unwind <TResult>(this IAggregateFluent <TResult> aggregate, FieldDefinition <TResult> field) { Ensure.IsNotNull(aggregate, "aggregate"); Ensure.IsNotNull(field, "field"); return(aggregate.Unwind <BsonDocument>(field)); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TDocument">The type of the document.</typeparam> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="source">The source.</param> /// <param name="fieldName">The name of the field to unwind.</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <TDocument, BsonDocument> Unwind <TDocument, TResult>(this IAggregateFluent <TDocument, TResult> source, string fieldName) { Ensure.IsNotNull(source, "source"); Ensure.IsNotNull(fieldName, "fieldName"); return(source.Unwind <BsonDocument>(fieldName)); }
private OverviewDetails LoadCashOverview() { OverviewDetails details = new OverviewDetails(); IAggregateFluent <HandHistory> cashGameHands = handCollection.Aggregate().Match(h => h.GameDescription.PokerFormat == PokerFormat.CashGame && h.GameDescription.Limit.Currency != Currency.PlayMoney); IAggregateFluent <UnwoundHand> actions = cashGameHands .Unwind <HandHistory, UnwoundHand>(h => h.HandActions) .Match(h => PlayerNames.Contains(h.HandActions.PlayerName)); if (!cashGameHands.Any()) { return(details); // Return empty result set if there are no hands available } details.Hands = cashGameHands.Count().First().Count; foreach (var profit in actions.Group(h => h.HandId, h => new { sum = h.Sum(h2 => h2.HandActions.Amount * h2.GameDescription.Limit.BigBlind) }).ToEnumerable()) { if (profit.sum > 0) { details.Winnings += profit.sum; } else { details.Losses += profit.sum; } } return(details); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TNewResult">The type of the new result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="field">The field to unwind.</param> /// <param name="options">The options.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TNewResult> Unwind <TResult, TNewResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field, AggregateUnwindOptions <TNewResult> options = null) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(field, nameof(field)); return(aggregate.Unwind( new ExpressionFieldDefinition <TResult>(field), options)); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="field">The field to unwind.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <BsonDocument> Unwind <TResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(field, nameof(field)); return(aggregate.Unwind( new ExpressionFieldDefinition <TResult>(field), new AggregateUnwindOptions <BsonDocument>())); }
protected override IAggregateFluent <MaterialReceivingVoucherView> ConvertToViewAggreagate(IAggregateFluent <MaterialReceivingVoucher> mappings, IExpressionContext <MaterialReceivingVoucher, MaterialReceivingVoucherView> context) { var unwind = new AggregateUnwindOptions <MaterialReceivingVoucher> { PreserveNullAndEmptyArrays = true }; var group = @" { _id: { _id : ""$_id"", code : ""$Code"", def_code : ""$DefCode"", name : ""$name"", value_to_search : ""$value_to_search"", is_published : ""$is_published"", created_date : ""$created_date"", last_modified : ""$last_modified"", delivery_code: ""$delivery_code"", supplier_code: ""$supplier_code"", category : ""$category"", description: ""$description"", document_date : ""$document_date"" }, infos: { ""$addToSet"": ""$infos"" } }"; var projection = @" { _id : ""$_id._id"", code : ""$_id.Code"", def_code : ""$_id.DefCode"", name : ""$_id.name"", value_to_search : ""$_id.value_to_search"", is_published : ""$_id.is_published"", created_date : ""$_id.created_date"", last_modified : ""$_id.last_modified"", delivery_code: ""$_id.delivery_code"", supplier_code: ""$_id.supplier_code"", category : ""$_id.category"", description: ""$_id.description"", document_date : ""$_id.document_date"" infos: ""infos"" }"; return(mappings .Unwind("infos", unwind) .Lookup("material", "infos.code", "code", "infos.store.material") .Unwind("infos.store.material", unwind) .Lookup("material_group", "infos.store.material.material_group_code", "code", "infos.store.material_group") .Unwind("infos.store.material_group", unwind) .Lookup("material_subgroup", "infos.store.material.material_subgroup_code", "code", "infos.store.material_subgroup") .Unwind("infos.store.material_subgroup", unwind) .Group(BsonDocument.Parse(group)) .Project(BsonDocument.Parse(projection)) .Lookup("supplier", "supplier_code", "code", "supplier") .Unwind("supplier", unwind) .As <MaterialReceivingVoucherView>().Match(context.GetPostExpression())); }
public static IAggregateFluent <TNewResult> Unwind <TResult, TNewResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field, IBsonSerializer <TNewResult> newResultSerializer) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(field, nameof(field)); return(aggregate.Unwind( new ExpressionFieldDefinition <TResult>(field), new AggregateUnwindOptions <TNewResult> { ResultSerializer = newResultSerializer })); }
/// <summary> /// Appends an unwind stage to the pipeline. /// </summary> /// <typeparam name="TDocument">The type of the document.</typeparam> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TNewResult">The type of the new result.</typeparam> /// <param name="source">The source.</param> /// <param name="field">The field to unwind.</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <TDocument, TNewResult> Unwind <TDocument, TResult, TNewResult>(this IAggregateFluent <TDocument, TResult> source, Expression <Func <TResult, object> > field) { Ensure.IsNotNull(source, "source"); Ensure.IsNotNull(field, "field"); var helper = new BsonSerializationInfoHelper(); helper.RegisterExpressionSerializer(field.Parameters[0], source.Collection.Settings.SerializerRegistry.GetSerializer <TResult>()); var serialiationInfo = helper.GetSerializationInfo(field.Body); return(source.Unwind <TNewResult>("$" + serialiationInfo.ElementName)); }
public void ShouldFetchCandidateListWhenSectorWiseSearch() { IMongoDatabase database = GetMongoDatabase(); IMongoCollection <BsonDocument> candidateCollection = database.GetCollection <BsonDocument>("Candidates"); IMongoCollection <BsonDocument> companyCollection = database.GetCollection <BsonDocument>("Companies"); var sectors = new[] { "java" }; IAggregateFluent <BsonDocument> candidateAgg = candidateCollection.Aggregate(); var let = new BsonDocument("compId", "$PreferredCompanies"); var operands = new BsonArray(); operands.Add("$$compId").Add("$_id"); var expression = new BsonDocument("$expr", new BsonDocument("$eq", operands)); PipelineDefinition <BsonDocument, BsonDocument> pipeline = PipelineDefinition <BsonDocument, BsonDocument> .Create(new BsonDocument("$match", expression)); candidateAgg = candidateAgg.Lookup(companyCollection, let, pipeline, "Array"); candidateAgg = candidateAgg.Unwind("Array"); FilterDefinition <BsonDocument> sectorFilters = Builders <BsonDocument> .Filter.In("Array.sectors", sectors); candidateAgg = candidateAgg.Match(sectorFilters); var fields = new BsonDocument { { "_id", "$_id" }, { "CompanyId", new BsonDocument { { "$first", "$CompanyId" } } } }; candidateAgg = candidateAgg.Group(fields); IEnumerable <BsonDocument> resultList = candidateAgg.ToList(); Assert.NotNull(resultList); }
protected override IAggregateFluent <MaterialDeliveryVoucherView> ConvertToViewAggreagate(IAggregateFluent <MaterialDeliveryVoucher> mappings, IExpressionContext <MaterialDeliveryVoucher, MaterialDeliveryVoucherView> context) { var unwind = new AggregateUnwindOptions <MaterialDeliveryVoucher> { PreserveNullAndEmptyArrays = true }; var group = @" { _id: { _id : ""$_id"", code : ""$Code"", def_code : ""$DefCode"", name : ""$name"", value_to_search : ""$value_to_search"", is_published : ""$is_published"", created_date : ""$created_date"", last_modified : ""$last_modified"", delivery_type: ""$delivery_type"", other_type: ""$other_type"", customer_code : ""$customer_code"", other_customer_code : ""$other_customer_code"", supplier_code : ""$supplier_code"", invoice_code : ""$invoice_code"", reason : ""$reason"", description: ""$description"", document_date : ""$document_date"" }, infos: { ""$addToSet"": ""$infos"" } }"; var projection = @" { _id: ""$_id._id"", code: ""$_id.code"", def_code: ""$_id.def_code"", name : ""$_id.name"", delivery_type: ""$_id.delivery_type"", other_type: ""$_id.other_type"", description: ""$_id.description"", value_to_search: ""$_id.value_to_search"", is_published: ""$_id.is_published"", created_date: ""$_id.created_date"", last_modified: ""$_id.last_modified"", customer_code : ""$_id.customer_code"", other_customer_code : ""$_id.other_customer_code"", supplier_code : ""$_id.supplier_code"", invoice_code : ""$_id.invoice_code"", reason : ""$_id.reason"", document_date: ""$_id.document_date"", infos: ""infos"" }"; var projection_store = @" { ""delivery"": 0, ""infos.store.material.receiving"": 0, ""infos.store.material.material_group"": 0, ""infos.store.material.material_subgroup"": 0 }"; var append_receivingmap = @" { $addFields: { ""receiving_map"": { $concat: [ ""$infos.receiving_code"", ""_"", ""$infos.code"" ] } } }"; var append_store = @" { $addFields: { ""infos.store.material"": ""$delivery"", ""infos.store.material_group"": ""$delivery.material_group"", ""infos.store.material_subgroup"": ""$delivery.material_subgroup"", ""infos.store.inventory"": ""$delivery.inventory"", ""infos.store.price"": ""$delivery.Price"", ""infos.store.receiving"": ""$delivery.receiving"", ""infos.store.last"": ""$Infos.quantity"" } }"; return(mappings .Unwind("infos", unwind) .AppendStage <BsonDocument>(BsonDocument.Parse(append_receivingmap)) .Lookup("material_for_delivery_view", "receiving_map", "receiving_map", "delivery") .Unwind("delivery", unwind) .AppendStage <BsonDocument>(BsonDocument.Parse(append_store)) .Project(BsonDocument.Parse(projection_store)) .Group(BsonDocument.Parse(group)) .Project(BsonDocument.Parse(projection)) .Lookup("customer", "customer_code", "code", "customer") .Unwind("customer", unwind) .Lookup("customer", "other_customer_code", "code", "other_customer") .Unwind("other_customer", unwind) .Lookup("supplier", "supplier_code", "code", "supplier") .Unwind("supplier", unwind) .As <MaterialDeliveryVoucherView>().Match(context.GetPostExpression())); }
public IDocumentAggregateCursor <TNewResult> Unwind <TNewResult>(Expression <Func <TResult, object> > arrayProperty) { var next = _fluentAggregateCursor.Unwind <TResult, TNewResult>(arrayProperty); return(CreateNextStage(next)); }