public static QueryContainer CreateReturnQuery(Action <QueryContainer, BoolBaseQueryDescriptor> modify = null)
        {
            var returnQuery     = new QueryContainer();
            var returnBoolQuery = new BoolBaseQueryDescriptor()
            {
            };

            ((IQueryContainer)returnQuery).Bool = returnBoolQuery;
            if (modify != null)
            {
                modify(returnQuery, returnBoolQuery);
            }
            return(returnQuery);
        }
        public static QueryContainer operator !(QueryContainer lbq)
        {
            if (lbq == null || ((IQueryContainer)lbq).IsConditionless)
            {
                var newConditionless = new QueryContainer();
                ((IQueryContainer)newConditionless).IsConditionless = true;
                return(newConditionless);
            }

            var f  = new QueryContainer();
            var fq = new BoolBaseQueryDescriptor();

            ((IBoolQuery)fq).MustNot = new[] { lbq };

            ((IQueryContainer)f).Bool = fq;
            return(f);
        }
 private static void JoinShouldOnSide(QueryContainer lbq, QueryContainer rbq, BoolBaseQueryDescriptor bq)
 {
     ((IBoolQuery)bq).Should = lbq.MergeShouldQueries(rbq);
 }
        public static QueryContainer operator |(QueryContainer leftQuery, QueryContainer rightQuery)
        {
            var defaultQuery = new QueryContainer();

            ((IQueryContainer)defaultQuery).IsConditionless = true;
            leftQuery  = leftQuery ?? defaultQuery;
            rightQuery = rightQuery ?? defaultQuery;
            var combined = new[] { leftQuery, rightQuery };

            if (combined.Any(bf => ((IQueryContainer)bf).IsConditionless))
            {
                return(combined.FirstOrDefault(bf => !((IQueryContainer)bf).IsConditionless) ?? defaultQuery);
            }

            var leftBoolQuery  = ((IQueryContainer)leftQuery).Bool;
            var rightBoolQuery = ((IQueryContainer)rightQuery).Bool;


            var f  = new QueryContainer();
            var fq = new BoolBaseQueryDescriptor();

            ((IBoolQuery)fq).Should   = new[] { leftQuery, rightQuery };
            ((IQueryContainer)f).Bool = fq;

            var mergeLeft  = !((IQueryContainer)leftQuery).IsStrict && (leftBoolQuery == null || ((IBoolQuery)leftBoolQuery).MinimumShouldMatch == null);
            var mergeRight = !((IQueryContainer)rightQuery).IsStrict && (rightBoolQuery == null || ((IBoolQuery)rightBoolQuery).MinimumShouldMatch == null);

            //if neither the left nor the right side represent a bool query join them
            if (((IQueryContainer)leftQuery).Bool == null && ((IQueryContainer)rightQuery).Bool == null)
            {
                ((IBoolQuery)fq).Should = leftQuery.MergeShouldQueries(rightQuery);
                return(f);
            }
            //if the left or right sight already is a bool query join the non bool query side of the
            //of the operation onto the other.
            if (((IQueryContainer)leftQuery).Bool != null &&
                ((IQueryContainer)rightQuery).Bool == null &&
                mergeLeft)
            {
                JoinShouldOnSide(leftQuery, rightQuery, fq);
            }
            else if (((IQueryContainer)rightQuery).Bool != null &&
                     ((IQueryContainer)leftQuery).Bool == null &&
                     mergeRight)
            {
                JoinShouldOnSide(rightQuery, leftQuery, fq);
            }
            //both sides already represent a bool query
            else
            {
                //both sides report that we may merge the shoulds
                if (mergeLeft && mergeRight &&
                    leftBoolQuery.CanJoinShould() &&
                    rightBoolQuery.CanJoinShould())
                {
                    ((IBoolQuery)fq).Should = leftQuery.MergeShouldQueries(rightQuery);
                }
                else
                {
                    //create a new nested bool with two separate should bool sections
                    ((IBoolQuery)fq).Should = new[] { leftQuery, rightQuery }
                };
            }
            return(f);
        }