/// <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)));
 }
Beispiel #3
0
        /// <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));
        }
Beispiel #4
0
 /// <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)));
 }
Beispiel #5
0
 /// <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)));
 }
Beispiel #6
0
 /// <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)));
 }
Beispiel #7
0
        /// <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
                       ));
        }