/// <summary> /// Appends a $facet stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="facets">The facets.</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <AggregateFacetResults> Facet <TResult>( this IAggregateFluent <TResult> aggregate, IEnumerable <AggregateFacet <TResult> > facets) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Facet(facets))); }
/// <summary> /// Appends a $facet 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="facets">The facets.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TNewResult> Facet <TResult, TNewResult>( this IAggregateFluent <TResult> aggregate, params AggregateFacet <TResult>[] facets) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Facet <TResult, TNewResult>(facets))); }
/// <summary> /// Appends a project 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="projection">The projection.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TNewResult> Project <TResult, TNewResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, TNewResult> > projection) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(projection, nameof(projection)); return(aggregate.Project <TNewResult>(new ProjectExpressionProjection <TResult, TNewResult>(projection))); }
/// <summary> /// Appends a group stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="group">The group projection.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <BsonDocument> Group <TResult>(this IAggregateFluent <TResult> aggregate, ProjectionDefinition <TResult, BsonDocument> group) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(group, nameof(group)); return(aggregate.Group <BsonDocument>(group)); }
/// <summary> /// Appends a project stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="projection">The projection.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <BsonDocument> Project <TResult>(this IAggregateFluent <TResult> aggregate, ProjectionDefinition <TResult, BsonDocument> projection) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(projection, nameof(projection)); return(aggregate.Project <BsonDocument>(projection)); }
public static async Task <PagedList <T> > Create(IAggregateFluent <T> source, int pageIndex, int pageSize) { var pagelist = new PagedList <T>(); await pagelist.InitializeAsync(source, pageIndex, pageSize); return(pagelist); }
/// <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))); }
public static IAggregateFluent <TNewResult> Unwind <TResult, TNewResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field, IBsonSerializer <TNewResult> newResultSerializer) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Unwind(field, new AggregateUnwindOptions <TNewResult> { ResultSerializer = newResultSerializer }))); }
protected override IAggregateFluent <EmployeeView> ConvertToViewAggreagate(IAggregateFluent <Employee> mappings, IExpressionContext <Employee, EmployeeView> context) { var afState = @"{ ""$addFields"": { ""has_user"": { ""$cond"": [{ ""$ne"": [ ""$user"", undefined ] }, true, false ] }, ""username"": ""$user.username"", ""uermission"": ""$user.uermission"" } }"; var pjState = @"{ ""User"": 0 }"; var unwind = new AggregateUnwindOptions <BsonDocument> { PreserveNullAndEmptyArrays = true }; // TODO: Mapping them JobPosition + Department + JobTitle return(mappings .Lookup("user", "user_code", "code", "user").Unwind("user", unwind) .Lookup("job_position", "job_position_code", "code", "job_position").Unwind("job_position", unwind) .Lookup("department", "job_position.department_code", "code", "department").Unwind("department", unwind) .Lookup("job_title", "job_position.job_title_code", "code", "job_title").Unwind("job_title", unwind) .AppendStage <BsonDocument>(BsonDocument.Parse(afState)) .Project(BsonDocument.Parse(pjState)) .As <EmployeeView>().Match(context.GetPostExpression())); }
/// <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 a $setWindowFields to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TWindowFields">The type of the added window fields.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="output">The window fields expression.</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <BsonDocument> SetWindowFields <TResult, TWindowFields>( this IAggregateFluent <TResult> aggregate, Expression <Func <ISetWindowFieldsPartition <TResult>, TWindowFields> > output) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.SetWindowFields(output))); }
//explain public static Task <BsonDocument> ExplainAggregation <TDocument, TResult>( this IMongoCollection <TDocument> collection, IAggregateFluent <TResult> aggregation, ExplainVerbosity verbosity) { IBsonSerializerRegistry serializerRegistry = collection.Settings.SerializerRegistry; IBsonSerializer <TDocument> serializer = serializerRegistry.GetSerializer <TDocument>(); MessageEncoderSettings encoderSettings = collection.GetMessageEncoderSettings(); var pipeline = new PipelineStagePipelineDefinition <TDocument, TResult>(aggregation.Stages); var renderedDefinition = pipeline.Render(serializer, serializerRegistry); var explainOperation = new AggregateOperation <TResult>( collection.CollectionNamespace, renderedDefinition.Documents, renderedDefinition.OutputSerializer, encoderSettings) .ToExplainOperation(verbosity); ICluster cluster = GetCluster(collection); ICoreSessionHandle session = NoCoreSession.NewHandle(); using (IReadBinding binding = new ReadPreferenceBinding(cluster, collection.Settings.ReadPreference, session)) { var cancelToken = new CancellationToken(); return(explainOperation.ExecuteAsync(binding, cancelToken)); } }
/// <summary> /// Restituisce la posizione dei mezzi per i quali c'è un messaggio di posizione giunto /// nelle ultime 24 ore. /// </summary> /// <param name="classiMezzo"></param> /// <returns></returns> public IEnumerable<MessaggioPosizione> Get(string[] classiMezzo) { IAggregateFluent<MessaggioPosizione_DTO> query = this.messaggiPosizione.Aggregate<MessaggioPosizione_DTO>() .SortBy(m => m.CodiceMezzo) .ThenByDescending(m => m.IstanteAcquisizione); if (classiMezzo != null && classiMezzo.Length > 0) { var filter = Builders<MessaggioPosizione_DTO> .Filter .AnyIn(m => m.ClassiMezzo, classiMezzo); query = query .Match(filter); } var query2 = query .Match(m => m.IstanteAcquisizione > DateTime.Now.AddHours(-24)) .Group(BsonDocument.Parse(@"{ _id: '$codiceMezzo', messaggio: { $first: '$$ROOT' } }")) .ReplaceRoot<MessaggioPosizione_DTO>("$messaggio"); var resultSet = query2 .ToEnumerable() .Select(dto => dto.ConvertToDomain()); return resultSet; }
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="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 a sortByCount stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TKey">The type of the key.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="id">The id.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <AggregateSortByCountResult <TKey> > SortByCount <TResult, TKey>( this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, TKey> > id) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.SortByCount(id))); }
protected override IAggregateFluent <EmployeeView> ConvertToViewAggreagate(IAggregateFluent <Employee> mappings, IExpressionContext <Employee, EmployeeView> context) { var afState = @"{ ""$addFields"": { ""has_user"": { ""$cond"": [ { ""$ne"": [""$user"", undefined ] }, true, false ] }, ""username"": ""$user.username"", ""permission"": { ""$cond"": [ { ""$ne"": [""$user.permission"", undefined ] }, ""$user.permission"", 0 ] } } }"; var pjState = @"{ ""user"": 0 }"; var unwind = new AggregateUnwindOptions <BsonDocument> { PreserveNullAndEmptyArrays = true }; return(mappings .Lookup("user", "_id", "code", "user").Unwind("user", unwind) .Lookup("facutly", "facutly_code", "_id", "facutly").Unwind("facutly", unwind) .Lookup("level", "level_code", "_id", "level").Unwind("level", unwind) .Lookup("major", "major_code", "_id", "major").Unwind("major", unwind) .AppendStage <BsonDocument>(BsonDocument.Parse(afState)) .Project(BsonDocument.Parse(pjState)) .As <EmployeeView>() .Match(context.GetPostExpression())); }
/// <summary> /// Appends a match stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="filter">The filter.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TResult> Match <TResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, bool> > filter) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(filter, nameof(filter)); return(aggregate.Match(new ExpressionFilterDefinition <TResult>(filter))); }
/// <summary> /// Appends a $replaceWith 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="newRoot">The new root.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IAggregateFluent <TNewResult> ReplaceWith <TResult, TNewResult>( this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, TNewResult> > newRoot) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.ReplaceWith(newRoot))); }
private void setupTournamentHands(TreeNode parentNode, PokerFormat format) { DatabaseHandler databaseHandler = DatabaseHandler.getInstance(); IAggregateFluent <TournamentSummary> tournaments = databaseHandler.GetAllTournaments() .Aggregate().Match(Builders <TournamentSummary> .Filter.Where(h => h.SitAndGo == (format == PokerFormat.SitAndGo))); IAggregateFluent <HandHistory> allHands = databaseHandler.GetAllHands().Aggregate() .Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.PokerFormat == format)); IEnumerable <AggregateResult <Buyin> > allBuyins = tournaments.Group(h => h.Buyin, h => new AggregateResult <Buyin> { result = h.Key }) .Sort(Builders <AggregateResult <Buyin> > .Sort.Ascending(b => b.result)) .ToEnumerable(); decimal lastBuyin = -0.01m; foreach (dynamic buyinObj in allBuyins) { Buyin buyin = buyinObj.result; if (buyin.Total == lastBuyin) { continue; } lastBuyin = buyin.Total; IAggregateFluent <HandHistory> hands = allHands.Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.TournamentSummary.Buyin.Total == buyin.Total)); GroupHandTreeNode buyinNode = new GroupHandTreeNode(string.Format("{0}{1} {2}", buyin.GetCurrencySymbol(), buyin.Total, HandCount(hands)), hands); dynamic allIds = hands.Group(h => h.GameDescription.TournamentId, h => new { name = h.Key }).ToEnumerable(); foreach (dynamic idObj in allIds) { string id = idObj.name; if (!string.IsNullOrWhiteSpace(id)) { IEnumerable <TournamentSummary> summaries = tournaments.Match(t => t.Id == id).ToEnumerable(); if (summaries.Count() > 0) { TournamentSummary summary = summaries.First(); IAggregateFluent <HandHistory> tournyHands = allHands.Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.TournamentId == summary.Id)); buyinNode.Nodes.Add(new HandsTreeNode(summary.ToString(), tournyHands)); } } } if (buyinNode.Nodes.Count > 0) { parentNode.Nodes.Add(buyinNode); } } }
/// <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); } } } }
public Task Run() { IAggregateFluent <FailChar> query = null; if (failCode.HasValue) { query = failCharSet.Where(w => w.FailCode == failCode.Value); } else { query = failCharSet.Aggregate(); } return(query.ForEachAsync(async f => { try { using (var httpClient = new HttpClient()) { httpClient.MaxResponseContentBufferSize = 256000; httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"); ChineseChar chineseChar = await CrawlerWorkItem.GetOneChinese(httpClient, uri, f.Unicode, len1, len2); if (chineseChar == null) { CrawlerWorkItem.PrintFail(0, f.Unicode, f.Text); CrawlerWorkItem.AddFailChar(failCharSet, 0, f.Unicode, f.Text, ""); return; } if (chineseCharSet.Any(a => a.Unicode == f.Unicode) == false) { chineseCharSet.Add(chineseChar); } failCharSet.Remove(f.Id); Console.WriteLine($"已成功修复 Unicode:{f.Unicode} 内容:{f.Text}"); } } catch (Exception ex) { CrawlerWorkItem.PrintFail(1, f.Unicode, f.Text); CrawlerWorkItem.AddFailChar(failCharSet, 1, f.Unicode, f.Text, ex.Message); } finally { await Task.Delay(200); } }).ContinueWith(t => { var foregroundColor = ConsoleColor.White; if (t.IsCompletedSuccessfully == false) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(t.Exception.ToString()); Console.ForegroundColor = foregroundColor; } t.Dispose(); })); }
public FilteredTreeNode(string title, IAggregateFluent <HandHistory> pipeline) : base(title) { Filter = new List <BsonDocument>(); foreach (IPipelineStageDefinition stage in pipeline.Stages) { Filter.Add(stage.ToBsonDocument()); } }
/// <summary> /// Appends a descending sort 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 sort by.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IOrderedAggregateFluent <TResult> SortByDescending <TResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field) { Ensure.IsNotNull(aggregate, nameof(aggregate)); Ensure.IsNotNull(field, nameof(field)); var sort = Builders <TResult> .Sort.Descending(field); return((IOrderedAggregateFluent <TResult>)aggregate.AppendStage(PipelineStageDefinitionBuilder.Sort(sort))); }
/// <summary> /// Appends a descending sort 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 sort by.</param> /// <returns> /// The fluent aggregate interface. /// </returns> public static IOrderedAggregateFluent <TResult> SortByDescending <TResult>(this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, object> > field) { Ensure.IsNotNull(aggregate, "aggregate"); Ensure.IsNotNull(field, "field"); return((IOrderedAggregateFluent <TResult>)aggregate.Sort( new DirectionalSortDefinition <TResult>(new ExpressionFieldDefinition <TResult>(field), SortDirection.Descending))); }
public async Task <long> SelectAllLabsCount() { IAggregateFluent <BsonDocument> query = _buildCollection.Aggregate().Group(new BsonDocument("_id", new BsonDocument(nameof(Build.Lab), $"${nameof(Build.Lab)}"))).Sort(new BsonDocument("_id", 1)); List <BsonDocument> grouping = await query.ToListAsync(); return(grouping.Count); }
private string HandCount(IAggregateFluent <HandHistory> hands) { /* * IEnumerable<AggregateCountResult> countResult = hands.Count().ToEnumerable(); * long count = countResult.Count() > 0 ? countResult.First().Count : 0; * return string.Format("({0} hands)", count); */ return(""); }
/// <summary> /// Appends a $bucketAuto stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="groupBy">The expression providing the value to group by.</param> /// <param name="buckets">The number of buckets.</param> /// <param name="options">The options (optional).</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <AggregateBucketAutoResult <TValue> > BucketAuto <TResult, TValue>( this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, TValue> > groupBy, int buckets, AggregateBucketAutoOptions options = null) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.BucketAuto(groupBy, buckets, options))); }
/// <summary> /// Appends a $bucket stage to the pipeline. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="aggregate">The aggregate.</param> /// <param name="groupBy">The expression providing the value to group by.</param> /// <param name="boundaries">The bucket boundaries.</param> /// <param name="options">The options.</param> /// <returns>The fluent aggregate interface.</returns> public static IAggregateFluent <AggregateBucketResult <TValue> > Bucket <TResult, TValue>( this IAggregateFluent <TResult> aggregate, Expression <Func <TResult, TValue> > groupBy, IEnumerable <TValue> boundaries, AggregateBucketOptions <TValue> options = null) { Ensure.IsNotNull(aggregate, nameof(aggregate)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Bucket(groupBy, boundaries, options))); }
/// <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)); }