/// <inheritdoc /> public async Task <ApiDataPage <Package> > GetPackages(string packageIdentifier, IQueryCollection queryParameters) { // Process Continuation token string continuationToken = null; if (queryParameters != null) { continuationToken = queryParameters[QueryConstants.ContinuationToken]; } continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null; // Create feed options FeedOptions feedOptions = new FeedOptions { ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb, EnableCrossPartitionQuery = true, MaxItemCount = FunctionSettingsConstants.MaxResultsPerPage, RequestContinuation = continuationToken, }; // Get iQueryable IQueryable <CosmosPackageManifest> query = this.cosmosDatabase.GetIQueryable <CosmosPackageManifest>(feedOptions); if (!string.IsNullOrWhiteSpace(packageIdentifier)) { query = query.Where(package => package.PackageIdentifier.Equals(packageIdentifier)); } // Finalize Query IDocumentQuery <CosmosPackageManifest> documentQuery = query.AsDocumentQuery(); // Fetch Current Package ApiDataPage <CosmosPackageManifest> apiDataDocument = await this.cosmosDatabase.GetByDocumentQuery <CosmosPackageManifest>(documentQuery); // Get Versions and convert. ApiDataPage <Package> packages = new ApiDataPage <Package>(); foreach (CosmosPackageManifest result in apiDataDocument.Items) { packages.Items.Add(result.ToPackage()); } packages.ContinuationToken = apiDataDocument.ContinuationToken != null?StringEncoder.EncodeContinuationToken(apiDataDocument.ContinuationToken) : null; return(packages); }
/// <inheritdoc /> public async Task <ApiDataPage <Locale> > GetLocales(string packageIdentifier, string packageVersion, string packageLocale, IQueryCollection queryParameters) { // Process Continuation token string continuationToken = null; if (queryParameters != null) { continuationToken = queryParameters[QueryConstants.ContinuationToken]; } continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null; // Fetch Current Package CosmosDocument <CosmosPackageManifest> cosmosDocument = await this.cosmosDatabase.GetByIdAndPartitionKey <CosmosPackageManifest>(packageIdentifier, packageIdentifier); // Get Versions and convert. ApiDataPage <Locale> locales = new ApiDataPage <Locale>(); locales.Items = cosmosDocument.Document.GetLocale(packageLocale, packageVersion).Select(locale => new Locale(locale)).ToList(); locales.ContinuationToken = null; return(locales); }
/// <inheritdoc /> public async Task <ApiDataPage <ManifestSearchResponse> > SearchPackageManifests(ManifestSearchRequest manifestSearchRequest, Dictionary <string, string> headers, IQueryCollection queryParameters) { // Create Working Set and return ApiDataPage <ManifestSearchResponse> apiDataPage = new ApiDataPage <ManifestSearchResponse>(); List <PackageManifest> manifests = new List <PackageManifest>(); List <ManifestSearchResponse> manifestSearchResponse = new List <ManifestSearchResponse>(); // Create feed options for inclusion search: -1 so we can get all matches in inclusion, then filter down. FeedOptions feedOptions = new FeedOptions { ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb, EnableCrossPartitionQuery = true, MaxItemCount = AllElements, RequestContinuation = null, }; if (manifestSearchRequest.FetchAllManifests || (manifestSearchRequest.Inclusions == null && manifestSearchRequest.Query == null)) { IQueryable <CosmosPackageManifest> query = this.cosmosDatabase.GetIQueryable <CosmosPackageManifest>(feedOptions); IDocumentQuery <CosmosPackageManifest> documentQuery = query.AsDocumentQuery(); ApiDataPage <CosmosPackageManifest> apiDataDocument = await this.cosmosDatabase.GetByDocumentQuery <CosmosPackageManifest>(documentQuery); manifests.AddRange(apiDataDocument.Items); } else { // Process Inclusions Models.Arrays.SearchRequestPackageMatchFilter inclusions = new Models.Arrays.SearchRequestPackageMatchFilter(); if (manifestSearchRequest.Inclusions != null) { inclusions.AddRange(manifestSearchRequest.Inclusions); } // Convert Query to inclusions to submit to cosmos if (manifestSearchRequest.Query != null) { inclusions.AddRange(this.queryList.Select(q => new Models.Objects.SearchRequestPackageMatchFilter() { PackageMatchField = q, RequestMatch = manifestSearchRequest.Query, })); } // Submit Inclusions to Cosmos // Due to join limitation on Cosmos - we are submitting each predicate separately. // TODO: Create a more efficient search - but this will suffice for now for a light weight reference. if (inclusions.Count > 0) { List <Task <ApiDataPage <PackageManifest> > > taskSet = new List <Task <ApiDataPage <PackageManifest> > >(); foreach (string packageMatchField in inclusions.Select(inc => inc.PackageMatchField).Distinct()) { // Create Predicate for search ExpressionStarter <PackageManifest> inclusionPredicate = PredicateBuilder.New <PackageManifest>(); foreach (SearchRequestPackageMatchFilter matchFilter in inclusions.Where(inc => inc.PackageMatchField.Equals(packageMatchField))) { // Some package match fields or types might not be supported by current version of search. // So we will check the supported list before adding any predicates. if (this.IsPackageMatchFieldSupported(matchFilter.PackageMatchField) && this.IsMatchTypeSupported(matchFilter.RequestMatch.MatchType)) { inclusionPredicate.Or(this.QueryPredicate(matchFilter.PackageMatchField, matchFilter.RequestMatch)); } } // Create Document Query IQueryable <PackageManifest> query = this.cosmosDatabase.GetIQueryable <PackageManifest>(feedOptions); query = query.Where(inclusionPredicate); IDocumentQuery <PackageManifest> documentQuery = query.AsDocumentQuery(); // Submit Query to Cosmos taskSet.Add(Task.Run(() => this.cosmosDatabase.GetByDocumentQuery(documentQuery))); } // Wait for Cosmos Queries to complete await Task.WhenAll(taskSet.ToArray()); // Process Manifests from Cosmos foreach (Task <ApiDataPage <PackageManifest> > task in taskSet) { manifests.AddRange(task.Result.Items); } manifests = manifests.Distinct().ToList(); } } // Process Filters if (manifestSearchRequest.Filters != null) { ExpressionStarter <PackageManifest> filterPredicate = PredicateBuilder.New <PackageManifest>(); foreach (SearchRequestPackageMatchFilter matchFilter in manifestSearchRequest.Filters) { if (this.IsPackageMatchFieldSupported(matchFilter.PackageMatchField) && this.IsMatchTypeSupported(matchFilter.RequestMatch.MatchType)) { filterPredicate.Or(this.QueryPredicate(matchFilter.PackageMatchField, matchFilter.RequestMatch)); } } manifests = manifests.Where(filterPredicate).ToList(); } foreach (PackageManifest manifest in manifests) { foreach (ManifestSearchResponse response in ManifestSearchResponse.GetSearchVersions(manifest)) { manifestSearchResponse.Add(response); } } // Consolidate Results manifestSearchResponse = ManifestSearchResponse.Consolidate(manifestSearchResponse).OrderBy(manifest => manifest.PackageIdentifier).ToList(); // Process results if (manifestSearchResponse.Count > manifestSearchRequest.MaximumResults && manifestSearchRequest.MaximumResults > 0) { manifestSearchResponse = manifestSearchResponse.GetRange(0, manifestSearchRequest.MaximumResults); } int maxPageCount = manifestSearchRequest.MaximumResults < FunctionSettingsConstants.MaxResultsPerPage && manifestSearchRequest.MaximumResults > 0 ? manifestSearchRequest.MaximumResults : FunctionSettingsConstants.MaxResultsPerPage; int totalResults = manifestSearchResponse.Count; if (totalResults > maxPageCount) { // Process Continuation Token ApiContinuationToken token = null; if (headers.ContainsKey(HeaderConstants.ContinuationToken)) { token = Parser.StringParser <ApiContinuationToken>(StringEncoder.DecodeContinuationToken(headers[HeaderConstants.ContinuationToken])); } else { token = new ApiContinuationToken() { Index = 0, MaxPageSize = maxPageCount, }; } // If index miss-match dump results and return no content. if (token.Index > manifestSearchResponse.Count - 1) { manifestSearchResponse = new List <ManifestSearchResponse>(); token = null; } else { int elementsRemaining = totalResults - token.Index; int elements = elementsRemaining < token.MaxPageSize ? elementsRemaining : token.MaxPageSize; manifestSearchResponse = manifestSearchResponse.GetRange(token.Index, elements); token.Index += elements; if (token.Index == totalResults) { token = null; } } apiDataPage.ContinuationToken = token != null?StringEncoder.EncodeContinuationToken(FormatJSON.None(token)) : null; } apiDataPage.Items = ManifestSearchResponse.Consolidate(manifestSearchResponse.ToList()); return(apiDataPage); }
/// <inheritdoc /> public async Task <ApiDataPage <PackageManifest> > GetPackageManifests(string packageIdentifier, IQueryCollection queryParameters) { // Process Continuation token string continuationToken = null; if (queryParameters != null) { continuationToken = queryParameters[QueryConstants.ContinuationToken]; } continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null; // Create feed options FeedOptions feedOptions = new FeedOptions { ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb, EnableCrossPartitionQuery = true, MaxItemCount = FunctionSettingsConstants.MaxResultsPerPage, RequestContinuation = continuationToken, }; // Get iQueryable IQueryable <PackageManifest> query = this.cosmosDatabase.GetIQueryable <PackageManifest>(feedOptions); if (!string.IsNullOrWhiteSpace(packageIdentifier)) { query = query.Where(package => package.PackageIdentifier.Equals(packageIdentifier)); } // Finalize Query IDocumentQuery <PackageManifest> documentQuery = query.AsDocumentQuery(); // Fetch Current Package ApiDataPage <PackageManifest> apiDataDocument = await this.cosmosDatabase.GetByDocumentQuery <PackageManifest>(documentQuery); apiDataDocument.ContinuationToken = apiDataDocument.ContinuationToken != null?StringEncoder.EncodeContinuationToken(apiDataDocument.ContinuationToken) : null; // Apply Version Filter string versionFilter = queryParameters[QueryConstants.Version]; if (!string.IsNullOrEmpty(versionFilter)) { foreach (PackageManifest pm in apiDataDocument.Items) { if (pm.Versions != null) { pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.PackageVersion.Equals(versionFilter))); } } } // Apply Channel Filter string channelFilter = queryParameters[QueryConstants.Channel]; if (!string.IsNullOrEmpty(channelFilter)) { foreach (PackageManifest pm in apiDataDocument.Items) { if (pm.Versions != null) { pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.Channel.Equals(channelFilter))); } } } return(apiDataDocument); }