public async Task<SearchResponse> SearchAsync(SearchRequest request, CancellationToken cancellationToken) { var frameworks = GetCompatibleFrameworksOrNull(request.Framework); IQueryable<Package> search = _context.Packages; search = ApplySearchQuery(search, request.Query); search = ApplySearchFilters( search, request.IncludePrerelease, request.IncludeSemVer2, request.PackageType, frameworks); var packageIds = search .Select(p => p.Id) .Distinct() .OrderBy(id => id) .Skip(request.Skip) .Take(request.Take); // This query MUST fetch all versions for each package that matches the search, // otherwise the results for a package's latest version may be incorrect. // If possible, we'll find all these packages in a single query by matching // the package IDs in a subquery. Otherwise, run two queries: // 1. Find the package IDs that match the search // 2. Find all package versions for these package IDs if (_context.SupportsLimitInSubqueries) { search = _context.Packages.Where(p => packageIds.Contains(p.Id)); } else { var packageIdResults = await packageIds.ToListAsync(cancellationToken); search = _context.Packages.Where(p => packageIdResults.Contains(p.Id)); } search = ApplySearchFilters( search, request.IncludePrerelease, request.IncludeSemVer2, request.PackageType, frameworks); var results = await search.ToListAsync(cancellationToken); var groupedResults = results .GroupBy(p => p.Id, StringComparer.OrdinalIgnoreCase) .Select(group => new PackageRegistration(group.Key, group.ToList())) .ToList(); return _searchBuilder.BuildSearch(groupedResults); }
public async Task <SearchResponse> SearchAsync( SearchRequest request, CancellationToken cancellationToken) { var results = await SearchAsync( request.Query, request.Skip, request.Take, request.IncludePrerelease, request.IncludeSemVer2, cancellationToken); return(_responseBuilder.BuildSearch(results)); }