//--------------------------------------------------------------------------- // Helper for FindText() test cases //--------------------------------------------------------------------------- internal void FindTextHelper(SampleText sampleText, SearchText searchTextType, FindResults result1, FindResults result2, FindResults result3, FindResults result4, Type expectedException) { string searchText; // Pre-Condition Verify text is expected value <<sampleText>> TS_SetText(sampleText, CheckType.IncorrectElementConfiguration); // Pre-Condition Text to search for is <<searchText>> TS_SetSearchText(out searchText, searchTextType, CheckType.Verification); // CallFindText(forwards, case-insensitive) <<result1>> if((searchTextType != SearchText.MatchesLastBlock) && (searchTextType != SearchText.MismatchedCaseLastBlock)) TS_FindText(searchText, false, false, result1, expectedException, CheckType.Verification); else m_TestStep++; // CallFindText(forwards, case-sensitive) <<result2>> if ((searchTextType != SearchText.MatchesLastBlock) && (searchTextType != SearchText.MismatchedCaseLastBlock)) TS_FindText(searchText, false, true, result2, expectedException, CheckType.Verification); else m_TestStep++; // CallFindText(backwards,case-insensitive) <<result3>> if ((searchTextType != SearchText.MatchesFirstBlock) && (searchTextType != SearchText.MismatchedCaseFirstBlock)) TS_FindText(searchText, true, false, result3, expectedException, CheckType.Verification); else m_TestStep++; // CallFindText(backwards,case-sensitive) <<result4>> if ((searchTextType != SearchText.MatchesFirstBlock) && (searchTextType != SearchText.MismatchedCaseFirstBlock)) TS_FindText(searchText, true, true, result4, expectedException, CheckType.Verification); else m_TestStep++; }
internal void TS_FindText(string searchText, bool backward, bool ignoreCase, FindResults results, Type expectedException, CheckType checkType) { int actualResult = 0; // contains flags for each "find result" that occurs string msg = "FindText(<<searchText>>," + (backward == true ? "backward" : "forward") + "," + (ignoreCase == true ? "ignore case" : "case-sensitive") + ")"; TextPatternRange findRange = null; TextPatternRange documentRange = Pattern_DocumentRange(CheckType.Verification); if ( expectedException == null ) Library.ValidateArgumentNonNull(searchText, "searchText cannot be null"); Range_FindText(documentRange, ref findRange, searchText, backward, ignoreCase, expectedException, checkType); // Identify actual range if (expectedException != null) actualResult += (int)FindResults.Exception; if (findRange == null) actualResult += (int)FindResults.Null; else { int compareResult = 0; // End point comparison object val = true; string findText = " "; // Required for FXCop Rule CA1820 string allText = " "; // text for entire range. TextPatternRange hiddenRange = null; // Get text from FindRange, get text for entire document Range_GetText(findRange, ref findText, -1, null, checkType); Range_GetText(documentRange, ref allText, -1, null, checkType); TrimTrailingCRLF(m_le, ref allText); TrimTrailingCRLF(m_le, ref findText); TrimTrailingCRLF(m_le, ref searchText); if (string.Compare(searchText, findText, false, CultureInfo.InvariantCulture) == 0) // case sensitive actualResult += (int)FindResults.MatchingRange; else if (string.Compare(searchText, findText, true, CultureInfo.InvariantCulture) == 0) // case insensitive { actualResult += (int)FindResults.MatchingRangeCaseLess; } // Do start points match? Range_CompareEndpoints(documentRange, TextPatternRangeEndpoint.Start, findRange, TextPatternRangeEndpoint.Start, ref compareResult, null, checkType); if (compareResult == 0) actualResult += (int)FindResults.MatchesFirst; // Do end points (mostly) match? Range_CompareEndpoints(documentRange, TextPatternRangeEndpoint.End, findRange, TextPatternRangeEndpoint.End, ref compareResult, null, checkType); if (TextLibrary.IsRichEdit(m_le)) { if ((compareResult >= 0) && (compareResult <= 2)) actualResult += (int)FindResults.MatchesLast; } else { if (compareResult == 0) actualResult += (int)FindResults.MatchesLast; } if (findText.Length == 0) actualResult += (int)FindResults.EmptyRange; Range_FindAttribute(findRange, ref hiddenRange, TextPattern.IsHiddenAttribute, val, true, null, checkType); if (hiddenRange == null) actualResult += (int)FindResults.NoHiddenText; } if ((actualResult & ((int)results)) > 0) Comment(msg + " returned " + Parse(results, expectedException)); else ThrowMe(checkType, msg + " failed to return " + Parse(results, expectedException)); m_TestStep++; }
//--------------------------------------------------------------------------- // Helper for FindAttribute() test cases //--------------------------------------------------------------------------- internal void FindAttributeHelper(SampleText sampleText, TypeValue typeValue, AttributeType attribType, bool backward, FindResults FindResults, Type expectedException) { bool isConsistentAttributes; IDictionary attributes = null; TextPatternRange documentRange = null; // Pre-Condition Verify text is expected value <<sampleText>> TS_SetText(sampleText, CheckType.IncorrectElementConfiguration); // Pre-Condition Identify & use <<attribType>> attributes documentRange = Pattern_DocumentRange(CheckType.IncorrectElementConfiguration); TS_GetAttributeValues(documentRange, out attributes, attribType, CheckType.Verification); // Pre-Condition Identify if document has consistent attribute values TS_VerifyAttributeRanges(attributes, out isConsistentAttributes); // Pre-Condition For each attribute, Val argument has <<typeValue>> type and <<typeValue>> value TS_SetAttributeValues(ref attributes, typeValue); // Call FindAttribute(<<backward>>) without errors (<<FindResults>>)/with <<expectedException, if not null>> TS_FindAttributes(attributes, typeValue, backward, FindResults, expectedException, CheckType.Verification); }
/// --------------------------------------------------------------------------- /// <summary>Parses values for enum</summary> /// --------------------------------------------------------------------------- static public string ParseType(FindResults value) { return ParseType(value.GetType().ToString(), value.ToString()); }
internal void TS_FindAttributes(IDictionary attributes, TypeValue typeValue, bool backward, FindResults FindResults, Type expectedException, CheckType checkType) { int errorCount = 0; bool isEqual = false; string text = ""; AutomationTextAttribute key = null; // key / name of attribute object valueToFind = null; // Value to perform FindAttribute on TextPatternRange callingRange = null; // Range to do FindAttribute on, default to entire document TextPatternRange findRange = null; // Range FindAttribute returns IDictionaryEnumerator enum1 = attributes.GetEnumerator(); // Enumerate through the dictionary callingRange = Pattern_DocumentRange(checkType); // Bug1134056: RichEdit oddness again. We can't just use the entire document range. TextLibrary.TrimRangeCRLF(m_le, callingRange); // Enumerate through attributes while (enum1.MoveNext()) { string keyString = ""; // get key and value for this attribute key = (AutomationTextAttribute)enum1.Key; keyString = Helpers.GetProgrammaticName(key); if (enum1.Value == TextPattern.MixedAttributeValue) // Try to get a smaller range for a non-mixed attribute value { Comment("Range has mixed attribute value for attribute " + keyString + ". Tryig to create single-character range to determine non-mixed attribute"); // Limit range to first character so we should get CONSISTENT attribute value(!) CreateEmptyRange(out callingRange, RangeLocation.Start, checkType); Range_ExpandToEnclosingUnit(callingRange, TextUnit.Character, null, checkType); Range_GetAttributeValue(callingRange, (AutomationTextAttribute)enum1.Key, ref valueToFind, null, checkType); if (valueToFind == TextPattern.MixedAttributeValue) { ThrowMe(checkType, "Single character range should(!) not have a mixed attribute value for attribute " + keyString + ". (International Locale perhaps?)"); } } else if (enum1.Value == AutomationElement.NotSupported) { Comment("Attribute " + keyString + " is not supported, skipping..."); continue; } else { valueToFind = enum1.Value; } SetValue(typeValue, key, ref valueToFind); // cast to correct type string msg = "FindAttribute(" + keyString + "," + (valueToFind != null ? valueToFind.ToString() : "NULL") + "," + (backward == true ? "backwards" : "forwards") + ")"; // Finally, find the attribute value(!) Range_FindAttribute(callingRange, ref findRange, (AutomationTextAttribute)enum1.Key, valueToFind, backward, expectedException, checkType); // Did we get correct results? switch (FindResults) { case FindResults.Exception: if (expectedException == null) ThrowMe(checkType, "Test code error, null expected exception is incorrect when getresult = " + Parse(FindResults, expectedException)); break; // actually takes place in Range_FindAttribute case FindResults.MatchingRange: if (findRange == null) { Comment(KNOWNISSUE + msg + " returned null range. Expected non-null range"); errorCount++; } else { Range_Compare(callingRange, findRange, ref isEqual, null, checkType); if (isEqual == false) { string callingText = "", findText = ""; Comment(KNOWNISSUE + "Comparison failed. Expected calling and actual range to have matching text"); Range_GetText(callingRange, ref callingText, -1, null, checkType); Comment("Calling range text = '" + TrimText(callingText, 512) + "'"); Range_GetText(findRange, ref findText, -1, null, checkType); Comment("Actual range text = '" + TrimText(findText, 512) + "'"); errorCount++; } } break; case FindResults.EmptyRange: if (findRange == null) { Comment(KNOWNISSUE + msg + " returned null range. Expected non-null range"); errorCount++; } else { Range_GetText(findRange, ref text, -1, null, checkType); if (text.Length != 0) { Comment(KNOWNISSUE + msg + " returned non-zero length text for range. Expected zero-length" + ", text = '" + TrimText(Range_GetText(findRange), 512) + "'"); errorCount++; } } break; case FindResults.Null: if (findRange != null) { if (key == TextPattern.TabsAttribute) { // This test condition failure is only really valid for this attribute // if we have a control with a non-zero length array of tab marks if (((double[])valueToFind).Length == 0) continue; // skip to next attribute } Comment(KNOWNISSUE + msg + " returned non-null range, expected null for attribute " + keyString + ", text = '" + TrimText(Range_GetText(findRange), 512) + "'"); errorCount++; } break; default: throw new ArgumentException("TS_FindAttributes() has no support for " + ParseType(FindResults)); } } if (errorCount == 0) Comment("FindAttribute(...) returned the correct range (" + ParseType(FindResults) + ")"); else ThrowMe(checkType, "FindAttribute(...) returned " + errorCount + " incorrect results"); m_TestStep++; }
static public string Parse(FindResults value, Type type) { switch (value) { case FindResults.MatchingRange: return "verify result MATCHING range (case sensitive)"; case FindResults.MatchingRangeCaseLess: return "matching range (case insensitive)"; case FindResults.MatchingFirstCaseLess: return "Matches first range and is caseless"; case FindResults.MatchingLastCaseLess: return "Matches last range and is caseless"; case FindResults.EmptyRange: return "verify result EMPTY range"; case FindResults.Null: return "verify result NULL"; case FindResults.Exception: if (type == null) throw new ArgumentException("Can't haveFindResults.Exception with null value for Type"); return ParseEx1(type); case FindResults.NoHiddenText: return "verify result has NO hidden text"; case FindResults.MatchesFirst: return "verify result MATCHES 1st instance of dup'd text"; case FindResults.MatchesLast: return "verify result MATCHES LAST instance of dup'd text"; default: throw new ArgumentException("Parse() has no support for " + ParseType(value)); } }
protected async Task <FindResults <TResult> > FindAsAsync <TResult>(object query) where TResult : class, new() { if (query == null) { throw new ArgumentNullException(nameof(query)); } var pagableQuery = query as IPagableQuery; // don't use caching with snapshot paging. bool allowCaching = IsCacheEnabled && (pagableQuery == null || pagableQuery.UseSnapshotPaging == false); Func <FindResults <TResult>, Task <FindResults <TResult> > > getNextPageFunc = async r => { if (!String.IsNullOrEmpty(r.ScrollId)) { var scrollResponse = await Context.ElasticClient.ScrollAsync <TResult>("2m", r.ScrollId).AnyContext(); return(new FindResults <TResult> { Documents = scrollResponse.Documents.ToList(), Total = r.Total, ScrollId = r.ScrollId }); } if (pagableQuery == null) { return(new FindResults <TResult>()); } pagableQuery.Page = pagableQuery.Page == null ? 2 : pagableQuery.Page + 1; return(await FindAsAsync <TResult>(query).AnyContext()); }; string cacheSuffix = pagableQuery?.ShouldUseLimit() == true?pagableQuery.Page?.ToString() ?? "1" : String.Empty; FindResults <TResult> result; if (allowCaching) { result = await GetCachedQueryResultAsync <FindResults <TResult> >(query, cacheSuffix : cacheSuffix).AnyContext(); if (result != null) { result.GetNextPageFunc = getNextPageFunc; return(result); } } var searchDescriptor = ConfigureSearchDescriptor(null, query); if (pagableQuery?.UseSnapshotPaging == true) { searchDescriptor.SearchType(SearchType.Scan).Scroll("2m"); } var response = await Context.ElasticClient.SearchAsync <TResult>(searchDescriptor).AnyContext(); if (!response.IsValid) { throw new ApplicationException($"Elasticsearch error code \"{response.ConnectionStatus.HttpStatusCode}\".", response.ConnectionStatus.OriginalException); } if (pagableQuery?.UseSnapshotPaging == true) { var scanResponse = response; response = await Context.ElasticClient.ScrollAsync <TResult>("2m", response.ScrollId).AnyContext(); if (!response.IsValid) { throw new ApplicationException($"Elasticsearch error code \"{response.ConnectionStatus.HttpStatusCode}\".", response.ConnectionStatus.OriginalException); } result = new FindResults <TResult> { Documents = response.Documents.ToList(), Total = scanResponse.Total, ScrollId = scanResponse.ScrollId, GetNextPageFunc = getNextPageFunc }; } else if (pagableQuery?.ShouldUseLimit() == true) { result = new FindResults <TResult> { Documents = response.Documents.Take(pagableQuery.GetLimit()).ToList(), Total = response.Total, HasMore = pagableQuery.ShouldUseLimit() && response.Documents.Count() > pagableQuery.GetLimit(), GetNextPageFunc = getNextPageFunc }; } else { result = new FindResults <TResult> { Documents = response.Documents.ToList(), Total = response.Total }; } result.Facets = response.ToFacetResults(); if (allowCaching) { var nextPageFunc = result.GetNextPageFunc; result.GetNextPageFunc = null; await SetCachedQueryResultAsync(query, result, cacheSuffix : cacheSuffix).AnyContext(); result.GetNextPageFunc = nextPageFunc; } return(result); }
public async Task <FindResults <T> > GetByIdsAsync(ICollection <string> ids, bool useCache = false, TimeSpan?expiresIn = null) { var results = new FindResults <T>(); if (ids == null || ids.Count == 0) { return(results); } var options = Options as IQueryOptions; if (options == null || !options.HasIdentity) { throw new NotSupportedException("Model type must implement IIdentity."); } if (IsCacheEnabled && useCache) { var cacheHits = await Cache.GetAllAsync <T>(ids.Distinct()).AnyContext(); results.Documents.AddRange(cacheHits.Where(kvp => kvp.Value.HasValue).Select(kvp => kvp.Value.Value)); results.Total = results.Documents.Count; var notCachedIds = ids.Except(results.Documents.Select(i => ((IIdentity)i).Id)).ToArray(); if (notCachedIds.Length == 0) { return(results); } } var itemsToFind = new List <string>(ids.Distinct().Except(results.Documents.Select(i => ((IIdentity)i).Id))); var multiGet = new MultiGetDescriptor(); if (GetParentIdFunc == null) { itemsToFind.ForEach(id => multiGet.Get <T>(f => f.Id(id).Index(GetIndexById(id)))); var multiGetResults = await Context.ElasticClient.MultiGetAsync(multiGet).AnyContext(); foreach (var doc in multiGetResults.Documents) { if (!doc.Found) { continue; } results.Documents.Add(doc.Source as T); itemsToFind.Remove(doc.Id); } } // fallback to doing a find if (itemsToFind.Count > 0 && (GetParentIdFunc != null || GetDocumentIndexFunc != null)) { results.Documents.AddRange((await FindAsync(new ElasticQuery().WithIds(itemsToFind)).AnyContext()).Documents); } if (IsCacheEnabled && useCache) { foreach (var item in results.Documents) { await Cache.SetAsync(((IIdentity)item).Id, item, expiresIn.HasValue?DateTime.UtcNow.Add(expiresIn.Value) : DateTime.UtcNow.AddSeconds(RepositoryConstants.DEFAULT_CACHE_EXPIRATION_SECONDS)).AnyContext(); } } results.Total = results.Documents.Count; return(results); }
public virtual async Task <FindResults <TResult> > FindAsAsync <TResult>(IRepositoryQuery query, ICommandOptions options = null) where TResult : class, new() { options = ConfigureOptions(options.As <T>()); bool useSnapshotPaging = options.ShouldUseSnapshotPaging(); // don't use caching with snapshot paging. bool allowCaching = IsCacheEnabled && useSnapshotPaging == false; await OnBeforeQueryAsync(query, options, typeof(TResult)).AnyContext(); await RefreshForConsistency(query, options).AnyContext(); async Task <FindResults <TResult> > GetNextPageFunc(FindResults <TResult> r) { var previousResults = r; if (previousResults == null) { throw new ArgumentException(nameof(r)); } string scrollId = previousResults.GetScrollId(); if (!String.IsNullOrEmpty(scrollId)) { var scrollResponse = await _client.ScrollAsync <TResult>(options.GetSnapshotLifetime(), scrollId).AnyContext(); _logger.LogRequest(scrollResponse, options.GetQueryLogLevel()); var results = scrollResponse.ToFindResults(); results.Page = previousResults.Page + 1; results.HasMore = scrollResponse.Hits.Count >= options.GetLimit() || scrollResponse.Hits.Count >= options.GetMaxLimit(); // clear the scroll if (!results.HasMore) { await _client.ClearScrollAsync(s => s.ScrollId(scrollId)); } return(results); } if (options.ShouldUseSearchAfterPaging()) { options.SearchAfterToken(previousResults.GetSearchAfterToken()); } if (options == null) { return(new FindResults <TResult>()); } options?.PageNumber(!options.HasPageNumber() ? 2 : options.GetPage() + 1); return(await FindAsAsync <TResult>(query, options).AnyContext()); } string cacheSuffix = options?.HasPageLimit() == true?String.Concat(options.GetPage().ToString(), ":", options.GetLimit().ToString()) : null; FindResults <TResult> result; if (allowCaching) { result = await GetCachedQueryResultAsync <FindResults <TResult> >(options, cacheSuffix : cacheSuffix).AnyContext(); if (result != null) { ((IGetNextPage <TResult>)result).GetNextPageFunc = async r => await GetNextPageFunc(r).AnyContext(); return(result); } } ISearchResponse <TResult> response; if (useSnapshotPaging == false || !options.HasSnapshotScrollId()) { var searchDescriptor = await CreateSearchDescriptorAsync(query, options).AnyContext(); if (useSnapshotPaging) { searchDescriptor.Scroll(options.GetSnapshotLifetime()); } if (query.ShouldOnlyHaveIds()) { searchDescriptor.Source(false); } response = await _client.SearchAsync <TResult>(searchDescriptor).AnyContext(); } else { response = await _client.ScrollAsync <TResult>(options.GetSnapshotLifetime(), options.GetSnapshotScrollId()).AnyContext(); } if (response.IsValid) { _logger.LogRequest(response, options.GetQueryLogLevel()); } else { if (response.ApiCall.HttpStatusCode.GetValueOrDefault() == 404) { return(new FindResults <TResult>()); } _logger.LogErrorRequest(response, "Error while searching"); throw new ApplicationException(response.GetErrorMessage(), response.OriginalException); } if (useSnapshotPaging) { result = response.ToFindResults(); result.HasMore = response.Hits.Count >= options.GetLimit(); // clear the scroll if (!result.HasMore) { var scrollId = result.GetScrollId(); if (!String.IsNullOrEmpty(scrollId)) { await _client.ClearScrollAsync(s => s.ScrollId(result.GetScrollId())); } } ((IGetNextPage <TResult>)result).GetNextPageFunc = GetNextPageFunc; } else { int limit = options.GetLimit(); result = response.ToFindResults(limit); result.HasMore = response.Hits.Count > limit || response.Hits.Count >= options.GetMaxLimit(); ((IGetNextPage <TResult>)result).GetNextPageFunc = GetNextPageFunc; } if (options.HasSearchAfter()) { result.SetSearchBeforeToken(); if (result.HasMore) { result.SetSearchAfterToken(); } } else if (options.HasSearchBefore()) { // reverse results bool hasMore = result.HasMore; result = new FindResults <TResult>(result.Hits.Reverse(), result.Total, result.Aggregations.ToDictionary(k => k.Key, v => v.Value), GetNextPageFunc, result.Data.ToDictionary(k => k.Key, v => v.Value)); result.HasMore = hasMore; result.SetSearchAfterToken(); if (result.HasMore) { result.SetSearchBeforeToken(); } } else if (result.HasMore) { result.SetSearchAfterToken(); } result.Page = options.GetPage(); if (!allowCaching) { return(result); } var nextPageFunc = ((IGetNextPage <TResult>)result).GetNextPageFunc; ((IGetNextPage <TResult>)result).GetNextPageFunc = null; await SetCachedQueryResultAsync(options, result, cacheSuffix : cacheSuffix).AnyContext(); ((IGetNextPage <TResult>)result).GetNextPageFunc = nextPageFunc; return(result); }
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 = Array.Empty <string>(); long stackTotal = 0; string stackFilterValue = stackFilter.Filter; bool isStackIdsNegated = false; //= 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); var systemFilterQuery = GetSystemFilterQuery(ctx, isStackIdsNegated); systemFilterQuery.FilterExpression(stackFilterValue); var softDeleteMode = isStackIdsNegated ? SoftDeleteQueryMode.All : SoftDeleteQueryMode.ActiveOnly; systemFilterQuery.EventStackFilterInverted(isStackIdsNegated); FindResults <Stack> results = null; var tooManyStacksCheck = await _cacheClient.GetAsync <long>(GetQueryHash(systemFilterQuery)); if (tooManyStacksCheck.HasValue) { stackTotal = tooManyStacksCheck.Value; } else { results = await _stackRepository.GetIdsByQueryAsync(q => systemFilterQuery.As <Stack>(), o => o.PageLimit(stackIdLimit).SoftDeleteMode(softDeleteMode)).AnyContext(); stackTotal = results.Total; } if (stackTotal > stackIdLimit) { if (!tooManyStacksCheck.HasValue) { await _cacheClient.SetAsync(GetQueryHash(systemFilterQuery), stackTotal, TimeSpan.FromMinutes(15)); } _logger.LogTrace("Query: {query} will be inverted due to id limit: {ResultCount}", stackFilterValue, stackTotal); isStackIdsNegated = !isStackIdsNegated; stackFilterValue = isStackIdsNegated ? stackFilter.InvertedFilter : stackFilter.Filter; systemFilterQuery.FilterExpression(stackFilterValue); softDeleteMode = isStackIdsNegated ? SoftDeleteQueryMode.All : SoftDeleteQueryMode.ActiveOnly; systemFilterQuery.EventStackFilterInverted(isStackIdsNegated); tooManyStacksCheck = await _cacheClient.GetAsync <long>(GetQueryHash(systemFilterQuery)); if (tooManyStacksCheck.HasValue) { stackTotal = tooManyStacksCheck.Value; } else { results = await _stackRepository.GetIdsByQueryAsync(q => systemFilterQuery.As <Stack>(), o => o.PageLimit(stackIdLimit).SoftDeleteMode(softDeleteMode)).AnyContext(); stackTotal = results.Total; } } if (stackTotal > stackIdLimit) { if (!tooManyStacksCheck.HasValue) { await _cacheClient.SetAsync(GetQueryHash(systemFilterQuery), stackTotal, TimeSpan.FromMinutes(15)); } throw new DocumentLimitExceededException("Please limit your search criteria."); } if (results?.Hits != null) { 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); }