private async Task <List <IGrouping <string, Package> > > SearchImplAsync( BaGetSearchRequest request, CancellationToken cancellationToken) { var frameworks = GetCompatibleFrameworksOrNull(request.Framework); var search = (IQueryable <Package>)_context.Packages.Where(p => p.Listed); if (!string.IsNullOrEmpty(request.Query)) { var query = request.Query.ToLower(); search = search.Where(p => p.Id.ToLower().Contains(query)); } if (!request.IncludePrerelease) { search = search.Where(p => !p.IsPrerelease); } if (!request.IncludeSemVer2) { search = search.Where(p => p.SemVerLevel != SemVerLevel.SemVer2); } if (!string.IsNullOrEmpty(request.PackageType)) { search = search.Where(p => p.PackageTypes.Any(t => t.Name == request.PackageType)); } if (frameworks != null) { search = search.Where(p => p.TargetFrameworks.Any(f => frameworks.Contains(f.Moniker))); } var packageIds = search.Select(p => p.Id) .OrderBy(id => id) .Distinct() .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)); } return(await search.GroupBy(p => p.Id).ToListAsync(cancellationToken)); }
public async Task <SearchResponse> SearchAsync(BaGetSearchRequest request, CancellationToken cancellationToken) { var result = new List <SearchResult>(); var packages = await SearchImplAsync(request, cancellationToken); foreach (var package in packages) { var versions = package.OrderByDescending(p => p.Version).ToList(); var latest = versions.First(); var versionResults = versions.Select(p => new SearchResultVersion( registrationLeafUrl: _url.GetRegistrationLeafUrl(p.Id, p.Version), p.Version, p.Downloads)); result.Add(new SearchResult( latest.Id, latest.Version, latest.Description, latest.Authors, latest.IconUrlString, latest.LicenseUrlString, latest.ProjectUrlString, registrationIndexUrl: _url.GetRegistrationIndexUrl(latest.Id), latest.Summary, latest.Tags, latest.Title, versions.Sum(p => p.Downloads), versionResults.ToList())); } return(new SearchResponse( result.Count, result, SearchContext.Default(_url.GetPackageMetadataResourceUrl()))); }
public Task <SearchResponse> SearchAsync(BaGetSearchRequest request, CancellationToken cancellationToken = default) { return(EmptySearchResponseTask); }
public async Task <SearchResponse> SearchAsync(SearchRequest request, CancellationToken cancellationToken) { return(await SearchAsync(BaGetSearchRequest.FromSearchRequest(request), cancellationToken)); }