Example #1
0
        public QueryOptimization(Snapshot snapshot, Query query, IEnumerable<BsonDocument> source, Collation collation)
        {
            if (query.Select == null) throw new ArgumentNullException(nameof(query.Select));

            _snapshot = snapshot;
            _query = query;
            _collation = collation;

            _queryPlan = new QueryPlan(snapshot.CollectionName)
            {
                // define index only if source are external collection
                Index = source != null ? new IndexVirtual(source) : null,
                Select = new Select(_query.Select, _query.Select.UseSource),
                ForUpdate = query.ForUpdate,
                Limit = query.Limit,
                Offset = query.Offset
            };
        }
Example #2
0
 /// <summary>
 /// Abstract method to be implement according pipe workflow
 /// </summary>
 public abstract IAsyncEnumerable <BsonDocument> Pipe(IAsyncEnumerable <IndexNode> nodes, QueryPlan query);
Example #3
0
        /// <summary>
        /// Query Pipe order
        /// - LoadDocument
        /// - IncludeBefore
        /// - Filter
        /// - OrderBy
        /// - OffSet
        /// - Limit
        /// - IncludeAfter
        /// - Select
        /// </summary>
        public override IEnumerable <BsonDocument> Pipe(IEnumerable <IndexNode> nodes, QueryPlan query)
        {
            // starts pipe loading document
            var source = this.LoadDocument(nodes);

            // do includes in result before filter
            foreach (var path in query.IncludeBefore)
            {
                source = this.Include(source, path);
            }

            // filter results according expressions
            foreach (var expr in query.Filters)
            {
                source = this.Filter(source, expr);
            }

            if (query.OrderBy != null)
            {
                // pipe: orderby with offset+limit
                source = this.OrderBy(source, query.OrderBy.Expression, query.OrderBy.Order, query.Offset, query.Limit);
            }
            else
            {
                // pipe: apply offset (no orderby)
                if (query.Offset > 0)
                {
                    source = source.Skip(query.Offset);
                }

                // pipe: apply limit (no orderby)
                if (query.Limit < int.MaxValue)
                {
                    source = source.Take(query.Limit);
                }
            }

            // do includes in result after filter
            foreach (var path in query.IncludeAfter)
            {
                source = this.Include(source, path);
            }

            // if is an aggregate query, run select transform over all resultset - will return a single value
            if (query.Select.All)
            {
                return(this.SelectAll(source, query.Select.Expression));
            }
            // run select transform in each document and return a new document or value
            else
            {
                return(this.Select(source, query.Select.Expression));
            }
        }
Example #4
0
        /// <summary>
        /// GroupBy Pipe Order
        /// - LoadDocument
        /// - Filter
        /// - OrderBy (to GroupBy)
        /// - GroupBy
        /// - HavingSelectGroupBy
        /// - OffSet
        /// - Limit
        /// </summary>
        public override IEnumerable <BsonDocument> Pipe(IEnumerable <IndexNode> nodes, QueryPlan query)
        {
            // starts pipe loading document
            var source = this.LoadDocument(nodes);

            // filter results according filter expressions
            foreach (var expr in query.Filters)
            {
                source = this.Filter(source, expr);
            }

            // run orderBy used in GroupBy (if not already ordered by index)
            if (query.OrderBy != null)
            {
                source = this.OrderBy(source, query.OrderBy.Expression, query.OrderBy.Order, 0, int.MaxValue);
            }

            // apply groupby
            var groups = this.GroupBy(source, query.GroupBy);

            // apply group filter and transform result
            var result = this.SelectGroupBy(groups, query.GroupBy);

            // apply offset
            if (query.Offset > 0)
            {
                result = result.Skip(query.Offset);
            }

            // apply limit
            if (query.Limit < int.MaxValue)
            {
                result = result.Take(query.Limit);
            }

            return(result);
        }
Example #5
0
        /// <summary>
        /// Query Pipe order
        /// - LoadDocument
        /// - IncludeBefore
        /// - Filter
        /// - OrderBy
        /// - OffSet
        /// - Limit
        /// - IncludeAfter
        /// - Select
        /// </summary>
        public override async IAsyncEnumerable <BsonDocument> Pipe(IAsyncEnumerable <IndexNode> nodes, QueryPlan query)
        {
            // starts pipe loading document
            var source = this.LoadDocument(nodes);

            // do includes in result before filter
            foreach (var path in query.IncludeBefore)
            {
                source = this.Include(source, path);
            }

            // filter results according expressions
            foreach (var expr in query.Filters)
            {
                source = this.Filter(source, expr);
            }

            if (query.OrderBy != null)
            {
                // pipe: orderby with offset+limit
                source = this.OrderBy(source, query.OrderBy.Expression, query.OrderBy.Order, query.Offset, query.Limit);
            }
            else
            {
                // pipe: apply offset (no orderby)
                if (query.Offset > 0)
                {
                    source = source.SkipAsync(query.Offset);
                }

                // pipe: apply limit (no orderby)
                if (query.Limit < int.MaxValue)
                {
                    source = source.TakeAsync(query.Limit);
                }
            }

            // do includes in result after filter
            foreach (var path in query.IncludeAfter)
            {
                source = this.Include(source, path);
            }

            var result = query.Select.All ?
                         this.SelectAll(source, query.Select.Expression) :
                         this.Select(source, query.Select.Expression);

            await foreach (var doc in result)
            {
                yield return(doc);
            }
        }