/// <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)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Group(group))); }
/// <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)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Match(filter))); }
/// <summary> /// Appends a match stage to the pipeline with an aggregation expression (i.e. $expr) /// </summary> /// <typeparam name="T">Any class that implements IEntity</typeparam> /// <param name="aggregate"></param> /// <param name="expression">{ $gt: ['$Property1', '$Property2'] }</param> /// <returns></returns> public static IAggregateFluent <T> MatchExpression <T>(this IAggregateFluent <T> aggregate, string expression) where T : IEntity { PipelineStageDefinition <T, T> stage = "{$match:{$expr:" + expression + "}}"; return(aggregate.AppendStage(stage)); }
/// <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)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Unwind(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)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Unwind(field))); }
/// <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)); return(aggregate.AppendStage(PipelineStageDefinitionBuilder.Project(projection))); }
/// <summary> /// Return event list. /// </summary> /// <returns></returns> public ListResult <EventListDTO> List(EventFilter filter) { IAggregateFluent <Event> eventAggregateFluent = this.MongoRepository.GetCollection <Event>().Aggregate(); if (filter.GeospatialQuery) { if (!filter.Meters.HasValue) { filter.Meters = 10000; } BsonDocument geoNearOptions = new BsonDocument { { "near", new BsonDocument { { "type", "Point" }, { "coordinates", new BsonArray { filter.Longitude.Value, filter.Latitude.Value } }, } }, { "maxDistance", filter.Meters }, { "includeLocs", "Location.Coordinates" }, { "distanceField", "Location.Distance" }, { "spherical", true } }; eventAggregateFluent = eventAggregateFluent.AppendStage( (PipelineStageDefinition <Event, Event>) new BsonDocument { { "$geoNear", geoNearOptions } } ); this.TelemetryClient.TrackEvent( EventNames.EventListLocation, new { filter.Latitude, filter.Longitude } ); } if (!string.IsNullOrEmpty(filter.EstablishmentId)) { eventAggregateFluent = eventAggregateFluent.Match( document => document.EstablishmentId == new ObjectId(filter.EstablishmentId)); this.TelemetryClient.TrackEvent( EventNames.EventListEstablishment, new { filter.EstablishmentId } ); } if (filter.Genre.HasValue) { eventAggregateFluent = eventAggregateFluent.Match( document => document.Genres.Contains(filter.Genre.Value)); this.TelemetryClient.TrackEvent( EventNames.EventListGenre, new { filter.Genre } ); } if (!string.IsNullOrEmpty(filter.Query)) { eventAggregateFluent = eventAggregateFluent.Match( document => document.Name.Contains(filter.Query) || document.Description.Contains(filter.Query) ); this.TelemetryClient.TrackEvent( EventNames.EventListQuery, new { filter.Query } ); } if (filter.DateFilter) { eventAggregateFluent = eventAggregateFluent.Match(document => ( (document.EndDate >= filter.StartDate && document.StartDate <= filter.StartDate) || (document.StartDate <= filter.EndDate && document.EndDate >= filter.EndDate) || (document.StartDate >= filter.StartDate && document.EndDate <= filter.EndDate) )); this.TelemetryClient.TrackEvent( EventNames.EventListDate, new { filter.StartDate, filter.EndDate } ); } if (!this.UserContext.EstablishmentId.HasValue) { this.RelevanceService.Register <Event, EventFilter>(filter); } IAggregateFluent <BsonDocument> aggregateFluent = eventAggregateFluent.Lookup( nameof(Establishment), "EstablishmentId", "_id", "Establishment" ).Unwind("Establishment"); aggregateFluent = filter.OrderType == OrderTypeEnum.Distance ? aggregateFluent.SortBy(document => document["Location"]["Distance"]) : aggregateFluent.SortByDescending(document => document["Relevance"]); IEnumerable <BsonDocument> documents = aggregateFluent .Skip((filter.Page - 1) * filter.PageSize) .Limit(filter.PageSize) .ToList(); IEnumerable <EventListDTO> events = documents.Select(document => new EventListDTO { Id = document["_id"].AsObjectId, Name = document["Name"].AsString, StartDate = document["StartDate"].ToUniversalTime(), EndDate = document["EndDate"].ToUniversalTime(), Genres = document["Genres"].AsBsonArray.Select(x => (GenreEnum)x.AsInt32), ImageThumbnail = document["ImageThumbnail"]["Uri"].AsString, Distance = document["Location"].AsBsonDocument.Contains("Distance") ? document["Location"]["Distance"].AsDouble : (double?)null, Establishment = new EventListEstablishmentDTO { Id = document["EstablishmentId"].AsObjectId, Name = document["Establishment"]["Name"].AsString, ImageThumbnail = document["Establishment"]["ImageThumbnail"]["Uri"].AsString, } } ).ToList(); return(new ListResult <EventListDTO>( events, aggregateFluent.Count().FirstOrDefault()?.Count ?? 0, filter )); }