Exemplo n.º 1
0
    public async Task CanGetByStatus()
    {
        Log.MinimumLevel = Microsoft.Extensions.Logging.LogLevel.Trace;
        var organizationRepository = GetService <IOrganizationRepository>();
        var organization           = await organizationRepository.GetByIdAsync(TestConstants.OrganizationId);

        Assert.NotNull(organization);

        await StackData.CreateSearchDataAsync(_repository, GetService <JsonSerializer>(), true);

        var appFilter = new AppFilter(organization);
        var stackIds  = await _repository.GetIdsByQueryAsync(q => q.AppFilter(appFilter).FilterExpression("status:open OR status:regressed").DateRange(DateTime.UtcNow.AddDays(-5), DateTime.UtcNow), o => o.PageLimit(o.GetMaxLimit()));

        Assert.Equal(2, stackIds.Total);
    }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            string filter = ctx.Source.GetFilterExpression();

            if (String.IsNullOrEmpty(filter))
            {
                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);

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

            // filter does not contain any stack filter criteria
            if (String.IsNullOrEmpty(stackFilter.Query) || !stackFilter.HasStackSpecificCriteria)
            {
                return;
            }

            const int stackIdLimit = 10000;

            string[] stackIds = null;

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

            if (isStackIdsNegated)
            {
                query = 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);
        }
        public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new()
        {
            if (!ctx.Source.ShouldEnforceEventStackFilter())
            {
                return;
            }

            // TODO: Handle search expressions as well
            string filter             = ctx.Source.GetFilterExpression() ?? String.Empty;
            bool   altInvertRequested = false;

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

            // when inverting to get excluded stack ids, add is_deleted as an alternate inverted criteria
            if (ctx.Options.GetSoftDeleteMode() == SoftDeleteQueryMode.ActiveOnly)
            {
                ctx.SetAlternateInvertedCriteria(new TermNode {
                    Field = "is_deleted", Term = "true"
                });
            }

            var stackFilter = await _eventStackFilter.GetStackFilterAsync(filter, ctx);

            const int stackIdLimit = 10000;

            string[] stackIds = null;

            string stackFilterValue  = stackFilter.Filter;
            bool   isStackIdsNegated = stackFilter.HasStatusOpen && !altInvertRequested;

            if (isStackIdsNegated)
            {
                stackFilterValue = stackFilter.InvertedFilter;
            }

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

            _logger.LogTrace("Source: {Filter} Stack Filter: {StackFilter} Inverted Stack Filter: {InvertedStackFilter}", filter, stackFilter.Filter, stackFilter.InvertedFilter);

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

                if (results.Total > stackIdLimit && isStackIdsNegated)
                {
                    _logger.LogTrace("Query: {query} will be inverted due to id limit: {ResultCount}", stackFilterValue, results.Total);
                    isStackIdsNegated = !isStackIdsNegated;
                    stackFilterValue  = isStackIdsNegated ? stackFilter.InvertedFilter : stackFilter.Filter;
                    systemFilterQuery.FilterExpression(stackFilterValue);
                    softDeleteMode = isStackIdsNegated ? SoftDeleteQueryMode.All : SoftDeleteQueryMode.ActiveOnly;
                    systemFilterQuery.EventStackFilterInverted(isStackIdsNegated);
                    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);
                }
            }

            // Strips stack only fields and stack only special fields
            string eventFilter = await _eventStackFilter.GetEventFilterAsync(filter, ctx);

            ctx.Source.FilterExpression(eventFilter);
        }