コード例 #1
0
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            string filter = ctx.Source.GetFilterExpression() ?? String.Empty;

            if (String.IsNullOrEmpty(filter) && !ctx.Source.ShouldEnforceEventStackFilter())
            {
                return;
            }

            // TODO: Handle search expressions as well
            bool altInvertRequested = false;

            if (filter.StartsWith("@!"))
            {
                altInvertRequested = true;
                filter             = filter.Substring(2);
                ctx.Source.FilterExpression(filter);
            }

            var stackFilter = await EventStackFilterQueryVisitor.RunAsync(filter, EventStackFilterQueryMode.Stacks, ctx);

            var invertedStackFilter = await EventStackFilterQueryVisitor.RunAsync(filter, EventStackFilterQueryMode.InvertedStacks, ctx);

            if (ctx.Options.GetSoftDeleteMode() == SoftDeleteQueryMode.ActiveOnly)
            {
                invertedStackFilter.Query = !String.IsNullOrEmpty(invertedStackFilter.Query) ? $"(is_deleted:true OR ({invertedStackFilter.Query}))" : "is_deleted:true";
            }

            // queries are the same, no need to allow inverting
            if (invertedStackFilter.Query == stackFilter.Query)
            {
                invertedStackFilter.IsInvertSuccessful = false;
            }

            const int stackIdLimit = 10000;

            string[] stackIds = null;

            string query             = stackFilter.Query;
            bool   isStackIdsNegated = stackFilter.HasStatusOpen && invertedStackFilter.IsInvertSuccessful && !altInvertRequested;

            if (isStackIdsNegated)
            {
                query = invertedStackFilter.Query;
            }

            if (String.IsNullOrEmpty(query) && (!ctx.Source.ShouldEnforceEventStackFilter() || ctx.Options.GetSoftDeleteMode() != SoftDeleteQueryMode.ActiveOnly))
            {
                return;
            }

            _logger.LogTrace("Stack filter: {StackFilter} Invert Success: {InvertSuccess} Inverted: {InvertedStackFilter}", stackFilter.Query, invertedStackFilter.IsInvertSuccessful, invertedStackFilter.Query);

            if (!(ctx is IQueryVisitorContextWithValidator))
            {
                var systemFilterQuery = GetSystemFilterQuery(ctx);
                systemFilterQuery.FilterExpression(query);
                var softDeleteMode = isStackIdsNegated ? SoftDeleteQueryMode.All : SoftDeleteQueryMode.ActiveOnly;
                var results        = await _stackRepository.GetIdsByQueryAsync(q => systemFilterQuery.As <Stack>(), o => o.PageLimit(stackIdLimit).SoftDeleteMode(softDeleteMode)).AnyContext();

                if (results.Total > stackIdLimit && (isStackIdsNegated || invertedStackFilter.IsInvertSuccessful))
                {
                    isStackIdsNegated = !isStackIdsNegated;
                    query             = isStackIdsNegated ? invertedStackFilter.Query : stackFilter.Query;
                    systemFilterQuery.FilterExpression(query);
                    softDeleteMode = isStackIdsNegated ? SoftDeleteQueryMode.All : SoftDeleteQueryMode.ActiveOnly;
                    results        = await _stackRepository.GetIdsByQueryAsync(q => systemFilterQuery.As <Stack>(), o => o.PageLimit(stackIdLimit).SoftDeleteMode(softDeleteMode)).AnyContext();
                }

                if (results.Total > stackIdLimit)
                {
                    throw new DocumentLimitExceededException("Please limit your search criteria.");
                }

                stackIds = results.Hits.Select(h => h.Id).ToArray();
            }

            _logger.LogTrace("Setting stack filter with {IdCount} ids", stackIds?.Length ?? 0);

            if (!isStackIdsNegated)
            {
                if (stackIds.Length > 0)
                {
                    ctx.Source.Stack(stackIds);
                }
                else
                {
                    ctx.Source.Stack("none");
                }
            }
            else
            {
                if (stackIds.Length > 0)
                {
                    ctx.Source.ExcludeStack(stackIds);
                }
            }

            var eventsResult = await EventStackFilterQueryVisitor.RunAsync(filter, EventStackFilterQueryMode.Events, ctx);

            ctx.Source.FilterExpression(eventsResult.Query);
        }