public static ISolrQuery ConditionalQuery(
            this ConditionalExpression expression, 
            Func<Expression,Expression> ifTrueBuilder, 
            Func<Expression, Expression> ifFalseBuilder, 
            MemberContext context)
        {
            ISolrQuery testPositive = expression.Test.GetSolrFilterQuery(context);
            ISolrQuery trueCase = ifTrueBuilder(expression.IfTrue).GetSolrFilterQuery(context);

            ISolrQuery testNegative = testPositive.CreateNotSolrQuery();
            ISolrQuery falseCase = ifFalseBuilder(expression.IfFalse).GetSolrFilterQuery(context);

            return GetMultipleCriteriaQuery(
                GetMultipleCriteriaQuery(testPositive, trueCase, SolrMultipleCriteriaQuery.Operator.AND),
                GetMultipleCriteriaQuery(testNegative, falseCase, SolrMultipleCriteriaQuery.Operator.AND),
                SolrMultipleCriteriaQuery.Operator.OR);
        }
        public static ISolrQuery GetSolrFilterQuery(this Expression expression, MemberContext context)
        {
            expression = expression.HandleConversion();
            ExpressionType nodeType = expression.NodeType;

            // No member access, try to calculate constant expression
            if (!context.HasMemberAccess(expression))
            {
                return ConstantToConstant(expression, Expression.Constant(true), (a, b) => (bool)a == (bool)b);
            }

            if (expression is BinaryExpression binaryExpression)
            {
                switch (nodeType)
                {
                    case ExpressionType.AndAlso:
                    {
                        ISolrQuery left = GetSolrFilterQuery(binaryExpression.Left, context);
                        ISolrQuery right = GetSolrFilterQuery(binaryExpression.Right, context);

                        string op = SolrMultipleCriteriaQuery.Operator.AND;
                        return GetMultipleCriteriaQuery(left, right, op);                        
                    }

                    case ExpressionType.OrElse:
                    {
                        ISolrQuery left = GetSolrFilterQuery(binaryExpression.Left, context);
                        ISolrQuery right = GetSolrFilterQuery(binaryExpression.Right, context);

                        string op = SolrMultipleCriteriaQuery.Operator.OR;
                        return GetMultipleCriteriaQuery(left, right, op);
                    }

                    case ExpressionType.Equal:
                    {
                        return binaryExpression.HandleEqual(context);
                    }

                    case ExpressionType.NotEqual:
                    {
                        Tuple<Expression, Expression, bool> memberToLeft = binaryExpression.MemberToLeft(context);
                        KeyValuePair<string, string> kvp = memberToLeft.MemberValue(context);

                        return kvp.Value == null
                            ? new SolrHasValueQuery(kvp.Key)
                            : new SolrQueryByField(kvp.Key, kvp.Value).CreateNotSolrQuery();

                    }

                    case ExpressionType.GreaterThan:
                    case ExpressionType.GreaterThanOrEqual:
                    case ExpressionType.LessThan:
                    case ExpressionType.LessThanOrEqual:
                    {
                        return binaryExpression.HandleComparison(context);
                    }
                }
            }

            if (expression is UnaryExpression unaryExpression)
            {
                switch (nodeType)
                {
                    case ExpressionType.Not:
                    {
                        ISolrQuery operand = GetSolrFilterQuery(unaryExpression.Operand, context);
                        ISolrQuery result = operand.CreateNotSolrQuery();
                        return result;
                    }                    
                }
            }

            if (expression is MethodCallExpression methodCallExpression)
            {
                return methodCallExpression.HandleMethodCall(context);
            }

            if (expression is MemberExpression memberExpression)
            {
                return memberExpression.HandleMemberAccess(context);
            }            

            if (expression is ConditionalExpression conditionalExpression)
            {
                return ConditionalQuery(conditionalExpression, t => t, f => f, context);
            }

            throw new InvalidOperationException(
                $"Node type {nodeType} not supported in filter query");
        }