public async Task <IActionResult> GetProviderIds([FromBody] SearchPublishedProvidersRequest request) { PublishedProviderIdSearchModel searchModel = new PublishedProviderIdSearchModel { Filters = ExtractFilters(request), SearchTerm = request.SearchTerm, SearchFields = request.SearchFields }; ApiResponse <IEnumerable <string> > response = await _publishingApiClient.SearchPublishedProviderIds(searchModel); var errorResult = response.IsSuccessOrReturnFailureResult("search"); if (errorResult != null) { return(errorResult); } return(Ok(response.Content)); }
public async Task <IActionResult> SearchPublishedProviderIds(PublishedProviderIdSearchModel searchModel) { if (searchModel == null) { _logger.Error("A null or invalid search model was provided for searching published provider ids"); return(new BadRequestObjectResult("An invalid search model was provided")); } try { IDictionary <string, string[]> searchModelDictionary = searchModel.Filters; List <Filter> filters = searchModelDictionary .Select(keyValueFilterPair => new Filter( keyValueFilterPair.Key, keyValueFilterPair.Value, IntegerFields.Contains(keyValueFilterPair.Key), "eq")) .ToList(); FilterHelper filterHelper = new FilterHelper(filters); IList <string> searchFields = searchModel.SearchFields?.ToList(); int searchResultsBatchSize = 1000; IList <string> selectFields = new[] { "id" }; IList <string> orderByFields = new[] { "id" }; string filter = filterHelper.BuildAndFilterQuery(); SearchResults <PublishedProviderIndex> searchResults = await Task.Run(() => { return(SearchRepository.Search(searchModel.SearchTerm, new SearchParameters { Top = searchResultsBatchSize, IncludeTotalResultCount = true, Select = selectFields, OrderBy = orderByFields, SearchFields = searchFields, Filter = filter })); }); ConcurrentBag <string> results = new ConcurrentBag <string>(); searchResults.Results.ForEach(_ => results.Add(_.Result.Id)); if (searchResults.TotalCount > searchResultsBatchSize) { SemaphoreSlim throttler = new SemaphoreSlim(10, 10); List <Task> searchTasks = new List <Task>(); int count = searchResultsBatchSize; while (count < searchResults.TotalCount) { SearchParameters searchParams = new SearchParameters { Skip = count, Top = searchResultsBatchSize, IncludeTotalResultCount = true, Select = selectFields, OrderBy = orderByFields, SearchFields = searchFields, Filter = filter }; await throttler.WaitAsync(); searchTasks.Add( Task.Run(async() => { try { SearchResults <PublishedProviderIndex> nextSearchResults = await SearchRepository.Search(searchModel.SearchTerm, searchParams); nextSearchResults.Results.ForEach(_ => results.Add(_.Result.Id)); } finally { throttler.Release(); } })); count += searchResultsBatchSize; } await TaskHelper.WhenAllAndThrow(searchTasks.ToArray()); } return(new OkObjectResult(results)); } catch (FailedToQuerySearchException exception) { _logger.Error(exception, $"Failed to query search with term: {searchModel.SearchTerm}"); return(new InternalServerErrorResult($"Failed to query search, with exception: {exception.Message}")); } }
public async Task GetsSearchPublishedProviderIdsShouldBatchAllPageResults() { string providerId = new RandomString(); string searchTerm = new RandomString(); PublishedProviderIdSearchModel searchModel = new PublishedProviderIdSearchModel { SearchTerm = searchTerm }; SearchParameters searchParametersOne = new SearchParameters { Skip = 0 }; SearchParameters searchParametersTwo = new SearchParameters { Skip = 1000 }; List <CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> > resultsOne = new List <CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> >(); resultsOne.AddRange(Enumerable.Range(1, 1000).Select(i => new CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> { Result = new PublishedProviderIndex { Id = $"{providerId}-One-{i}" } })); SearchResults <PublishedProviderIndex> firstPageSearchResults = new SearchResults <PublishedProviderIndex> { TotalCount = 1500, Results = resultsOne }; List <CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> > resultsTwo = new List <CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> >(); resultsTwo.AddRange(Enumerable.Range(1, 500).Select(i => new CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> { Result = new PublishedProviderIndex { Id = $"{providerId}-Two-{i}" } })); SearchResults <PublishedProviderIndex> secondPageSearchResults = new SearchResults <PublishedProviderIndex> { TotalCount = 1500, Results = resultsTwo }; AndTheSearchResults(new SearchModel { SearchTerm = searchTerm }, searchParametersOne, firstPageSearchResults); AndTheSearchResults(new SearchModel { SearchTerm = searchTerm }, searchParametersTwo, secondPageSearchResults); IActionResult result = await WhenSearchPublishedProviderIdsIsMade(searchModel); result .Should() .BeOfType <OkObjectResult>() .Should() .NotBeNull(); OkObjectResult okObjectResult = result as OkObjectResult; okObjectResult .Value .Should() .NotBeNull() .And .BeOfType <ConcurrentBag <string> >(); ConcurrentBag <string> publishedProviderIds = okObjectResult.Value as ConcurrentBag <string>; publishedProviderIds .Should() .HaveCount(1500); }
private async Task <IActionResult> WhenSearchPublishedProviderIdsIsMade( PublishedProviderIdSearchModel publishedProviderIdSearchModel) { return(await _service.SearchPublishedProviderIds(publishedProviderIdSearchModel)); }
public async Task GetsSearchPublishedProviderIds() { string providerIdOne = new RandomString(); string providerIdTwo = new RandomString(); string searchTerm = new RandomString(); PublishedProviderIdSearchModel searchModel = new PublishedProviderIdSearchModel { SearchTerm = searchTerm }; SearchResults <PublishedProviderIndex> searchResults = new SearchResults <PublishedProviderIndex> { Results = new List <CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> > { new CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> { Result = new PublishedProviderIndex { Id = providerIdOne } }, new CalculateFunding.Repositories.Common.Search.SearchResult <PublishedProviderIndex> { Result = new PublishedProviderIndex { Id = providerIdTwo } } } }; AndTheSearchResults(new SearchModel { SearchTerm = searchTerm }, searchResults); IActionResult result = await WhenSearchPublishedProviderIdsIsMade(searchModel); result .Should() .BeOfType <OkObjectResult>() .Should() .NotBeNull(); OkObjectResult okObjectResult = result as OkObjectResult; okObjectResult .Value .Should() .NotBeNull() .And .BeOfType <ConcurrentBag <string> >(); ConcurrentBag <string> publishedProviderIds = okObjectResult.Value as ConcurrentBag <string>; publishedProviderIds .Should() .HaveCount(2); publishedProviderIds .Should() .BeEquivalentTo(new[] { providerIdOne, providerIdTwo }); }