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); }