예제 #1
0
        /// <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));
        }
예제 #5
0
        /// <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));
        }
예제 #6
0
        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
            }));
        }
예제 #11
0
        /// <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));
        }
예제 #12
0
        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()));
        }
예제 #14
0
        public IDocumentAggregateCursor <TNewResult> Unwind <TNewResult>(Expression <Func <TResult, object> > arrayProperty)
        {
            var next = _fluentAggregateCursor.Unwind <TResult, TNewResult>(arrayProperty);

            return(CreateNextStage(next));
        }