protected override Expression VisitSelect(SelectExpression select)
            {
                if (select.From.NodeType != (ExpressionType)MongoExpressionType.Collection)
                {
                    throw new InvalidQueryException("The query is too complex to be processed by MongoDB. Try building a map-reduce query by hand or simplifying the query and using Linq-to-Objects.");
                }

                bool hasAggregates = new AggregateChecker().HasAggregates(select);

                if (select.GroupBy != null)
                {
                    _isMapReduce = true;
                }

                else if (hasAggregates)
                {
                    if (select.Fields.Count == 1 && select.Fields[0].Expression.NodeType == (ExpressionType)MongoExpressionType.Aggregate)
                    {
                        var aggregateExpression = (AggregateExpression)select.Fields[0].Expression;
                        if (aggregateExpression.AggregateType == AggregateType.Count)
                        {
                            _isCount = true;
                        }
                    }

                    if (!_isCount)
                    {
                        _isMapReduce = true;
                    }
                }

                Visit(select.Where);
                return(select);
            }
        private static bool CanMergeWithFrom(SelectExpression select, bool isTopLevel)
        {
            var fromSelect = select.From as SelectExpression;
            if (fromSelect == null)
                return false;

            var fromIsSimpleProjection = IsSimpleProjection(fromSelect);
            var fromIsNameMapProjection = IsNameMapProjection(fromSelect);
            if (!fromIsSimpleProjection && !fromIsNameMapProjection)
                return false;

            var selectIsNameMapProjection = IsNameMapProjection(select);
            var selectHasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
            var selectHasGroupBy = select.GroupBy != null;
            var selectHasAggregates = new AggregateChecker().HasAggregates(select);
            var fromHasOrderBy = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
            var fromHasGroupBy = fromSelect.GroupBy != null;

            if (selectHasOrderBy && fromHasOrderBy)
                return false;

            if (selectHasGroupBy && fromHasGroupBy)
                return false;

            if(fromHasOrderBy && (selectHasGroupBy || selectHasAggregates || select.IsDistinct))
                return false;

            if(fromHasGroupBy && select.Where != null)
                return false;

            if(fromSelect.Take != null && (select.Take != null || select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
                return false;

            if(fromSelect.Skip != null && (select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
                return false;

            if (fromSelect.IsDistinct && (select.Take != null || select.Skip != null || !selectIsNameMapProjection || selectHasGroupBy || selectHasAggregates || (selectHasOrderBy && !isTopLevel)))
                return false;

            return true;
        }
        private static bool CanMergeWithFrom(SelectExpression select, bool isTopLevel)
        {
            var fromSelect = select.From as SelectExpression;

            if (fromSelect == null)
            {
                return(false);
            }

            var fromIsSimpleProjection  = IsSimpleProjection(fromSelect);
            var fromIsNameMapProjection = IsNameMapProjection(fromSelect);

            if (!fromIsSimpleProjection && !fromIsNameMapProjection)
            {
                return(false);
            }

            var selectIsNameMapProjection = IsNameMapProjection(select);
            var selectHasOrderBy          = select.OrderBy != null && select.OrderBy.Count > 0;
            var selectHasGroupBy          = select.GroupBy != null;
            var selectHasAggregates       = new AggregateChecker().HasAggregates(select);
            var fromHasOrderBy            = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
            var fromHasGroupBy            = fromSelect.GroupBy != null;

            if (selectHasOrderBy && fromHasOrderBy)
            {
                return(false);
            }

            if (selectHasGroupBy && fromHasGroupBy)
            {
                return(false);
            }

            if (fromHasOrderBy && (selectHasGroupBy || selectHasAggregates || select.IsDistinct))
            {
                return(false);
            }

            if (fromHasGroupBy && select.Where != null)
            {
                return(false);
            }

            if (fromSelect.Take != null && (select.Take != null || select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
            {
                return(false);
            }

            if (fromSelect.Skip != null && (select.Skip != null || select.IsDistinct || selectHasAggregates || selectHasGroupBy))
            {
                return(false);
            }

            if (fromSelect.IsDistinct && (select.Take != null || select.Skip != null || !selectIsNameMapProjection || selectHasGroupBy || selectHasAggregates || (selectHasOrderBy && !isTopLevel)))
            {
                return(false);
            }

            return(true);
        }