public string BuildTagQueryString(int pageNumber, string currentPath) { var query = "?"; var paramz = new List <string>(); if (pageNumber > 1) { paramz.Add("p=" + pageNumber); } if (QuerySortBy != QuerySortBy.DateCreated) { paramz.Add("s=" + QuerySortBy.ToString().ToLower()); } if (QueryRange != QueryRange.Forever) { paramz.Add("r=" + QueryRange.ToString().ToLower()); } if (paramz.Count == 0) { return(currentPath); } query += string.Join('&', paramz); return(query); }
public string BuildSearchQueryString(int pageNumber) { var query = $"/search?q={SearchTerm}"; var paramz = new List <string>(); if (SearchResultsType != SearchResultsType.All) { paramz.Add("t=" + SearchResultsType.ToString().ToLower()); } if (pageNumber > 1) { paramz.Add("p=" + pageNumber); } if (QuerySortBy != QuerySortBy.DateCreated) { paramz.Add("s=" + QuerySortBy.ToString().ToLower()); } if (QueryRange != QueryRange.Forever) { paramz.Add("r=" + QueryRange.ToString().ToLower()); } if (paramz.Count == 0) { return(query); } query += "&" + string.Join('&', paramz); return(query); }
public string BuildTagQueryString(QueryRange queryRange) { var query = "?"; if (CurrentPage > 1) { query += "p=" + CurrentPage + "&"; } if (QuerySortBy != QuerySortBy.DateCreated) { query += "s=" + QuerySortBy.ToString().ToLower() + "&"; } query += "r=" + queryRange.ToString().ToLower(); return(query); }
public string BuildTagQueryString(QuerySortBy querySortBy) { var query = "?"; if (CurrentPage > 1) { query += "p=" + CurrentPage + "&"; } query += "s=" + querySortBy.ToString().ToLower(); if (QueryRange != QueryRange.Forever) { query += "&r=" + QueryRange.ToString().ToLower(); } return(query); }
public string BuildSearchQueryString(QueryRange queryRange) { var query = $"/search?q={SearchTerm}"; if (SearchResultsType != SearchResultsType.All) { query += $"&t={SearchResultsType.ToString().ToLower()}"; } if (CurrentPage > 1) { query += "&p=" + CurrentPage; } if (QuerySortBy != QuerySortBy.DateCreated) { query += "&s=" + QuerySortBy.ToString().ToLower(); } query += "&r=" + queryRange.ToString().ToLower(); return(query); }
/// <summary> /// Returns a page of galleries that match a search term. /// </summary> /// <param name="term">The search term to use to search for galleries.</param> /// <param name="searchStatus">Choose whether or not to specify status for refining searches.</param> /// <param name="page">The page of galleries to return results from, for the first page use 1.</param> /// <param name="pageSize">The maximum number of galleries to return per page, i.e. 20.</param> /// <param name="maxResults">The maximum number of galleries to get paged results for, i.e. how many pages to look for.</param> /// <param name="categoryId">Optionally specify a categoryId to limit results to a specific category.</param> /// <param name="querySortBy">How should we sort the search results?</param> /// <param name="queryRange">What time range should the search results cover?</param> public async Task <PagedResultSet <Gallery> > SearchForGalleriesAsync(string term, string categoryId = null, SearchStatus searchStatus = SearchStatus.NotSpecified, int page = 1, int pageSize = 20, int maxResults = 500, QuerySortBy querySortBy = QuerySortBy.DateCreated, QueryRange queryRange = QueryRange.Forever) { if (!term.HasValue() && !categoryId.HasValue() && searchStatus == SearchStatus.NotSpecified) { throw new ArgumentException("Supply a term, categoryId or searchStatus"); } if (pageSize < 1) { throw new ArgumentOutOfRangeException(nameof(pageSize), "pageSize must be a positive number"); } if (page < 1) { page = 1; } // limit page size to avoid incurring unnecessary charges and increasing latency if (pageSize > 100) { pageSize = 100; } // limit how big the id query is to avoid unnecessary charges and to keep latency within an acceptable range if (maxResults > 500) { maxResults = 500; } var nameClause = string.Empty; if (term.HasValue()) { nameClause = "CONTAINS(g.Name, @term, true)"; } var statusClause = string.Empty; if (searchStatus == SearchStatus.Active) { if (nameClause.HasValue()) { statusClause = "AND "; } statusClause += "g.Active = true"; } else if (searchStatus == SearchStatus.Inactive) { if (nameClause.HasValue()) { statusClause = "AND "; } statusClause += "g.Active = false"; } var categoryClause = string.Empty; if (categoryId.HasValue()) { if (nameClause.HasValue() || statusClause.HasValue()) { categoryClause = "AND "; } categoryClause += $"g.CategoryId = '{categoryId}'"; } var orderClause = querySortBy switch { QuerySortBy.DateCreated => "g.Created DESC", //QuerySortBy.Popularity => "g.Views DESC, g.Created DESC", // galleries don't support the popularity option yet, so just use the default QuerySortBy.Popularity => "g.Created DESC", QuerySortBy.Comments => "g.CommentCount DESC, g.Created DESC", _ => null }; var rangeClause = string.Empty; if (queryRange != QueryRange.Forever) { var rangeFrom = queryRange switch { QueryRange.LastYear => DateTime.Now - TimeSpan.FromDays(365), QueryRange.LastMonth => DateTime.Now - TimeSpan.FromDays(30), QueryRange.LastWeek => DateTime.Now - TimeSpan.FromDays(7), _ => default }; rangeClause = $"AND g.Created >= \"{rangeFrom.ToString(Constants.CosmosDbDateTimeFormatString)}\""; } var queryText = $"SELECT TOP @maxResults g.id AS Id, g.CategoryId AS PartitionKey FROM g WHERE {nameClause} {statusClause} {categoryClause} {rangeClause} ORDER BY {orderClause}"; // get the complete list of ids var queryDefinition = new QueryDefinition(queryText) .WithParameter("@maxResults", maxResults) .WithParameter("@term", term); var databaseIds = await Server.GetIdsByQueryAsync(Constants.GalleriesContainerName, queryDefinition); // now with all the ids we know how many total results there are and so can populate paging info var pagedResultSet = new PagedResultSet <Gallery> { PageSize = pageSize, TotalResults = databaseIds.Count, CurrentPage = page }; // don't let users try and request a page that doesn't exist if (page > pagedResultSet.TotalPages) { return(null); } // now just retrieve a page's worth of galleries from the results var offset = (page - 1) * pageSize; var itemsToGet = databaseIds.Count >= pageSize ? pageSize : databaseIds.Count; // if we're on the last page just get the remaining items if (page == pagedResultSet.TotalPages) { itemsToGet = pagedResultSet.TotalResults - offset; } if (databaseIds.Count == 0) { return(pagedResultSet); } var pageIds = databaseIds.GetRange(offset, itemsToGet); // this is how we used to do it, and it used to be 3-5x slower //foreach (var id in pageIds) // pagedResultSet.Results.Add(await GetGalleryAsync(id.PartitionKey, id.Id)); var unorderedGalleries = new List <Gallery>(); var tasks = new List <Task>(); foreach (var pageId in pageIds) { tasks.Add(Task.Run(async() => { var g = await GetGalleryAsync(pageId.PartitionKey, pageId.Id); lock (unorderedGalleries) unorderedGalleries.Add(g); })); } var t = Task.WhenAll(tasks); t.Wait(); // put the unordered galleries into the results list in the same order as the ids were retrieved from the db foreach (var id in pageIds) { pagedResultSet.Results.Add(unorderedGalleries.SingleOrDefault(g => g.Id == id.Id)); } return(pagedResultSet); }
/// <summary> /// Returns a page of images that match a search term. /// </summary> /// <param name="term">The search term to use to search for galleries.</param> /// <param name="page">The page of galleries to return results from, for the first page use 1.</param> /// <param name="pageSize">The maximum number of galleries to return per page, i.e. 20.</param> /// <param name="maxResults">The maximum number of galleries to get paged results for, i.e. how many pages to look for.</param> /// <param name="includeInactiveGalleries">Indicates whether or not images in inactive (not active) galleries should be returned. False by default.</param> /// <param name="querySortBy">How should we sort the search results?</param> /// <param name="queryRange">What time range should the search results cover?</param> public async Task <PagedResultSet <Image> > SearchForImagesAsync(string term, int page = 1, int pageSize = 20, int maxResults = 500, bool includeInactiveGalleries = false, QuerySortBy querySortBy = QuerySortBy.DateCreated, QueryRange queryRange = QueryRange.Forever) { if (string.IsNullOrEmpty(term)) { throw new ArgumentNullException(nameof(term)); } if (pageSize < 1) { throw new ArgumentOutOfRangeException(nameof(pageSize), "pageSize must be a positive number"); } if (page < 1) { page = 1; } // limit page size to avoid incurring unnecessary charges and increasing latency if (pageSize > 100) { pageSize = 100; } // limit how big the id query is to avoid unnecessary charges and to keep latency within an acceptable range if (maxResults > 500) { maxResults = 500; } var orderClause = querySortBy switch { QuerySortBy.DateCreated => "i.Created DESC", QuerySortBy.Popularity => "i.Views DESC, i.Created DESC", QuerySortBy.Comments => "i.CommentCount DESC, i.Created DESC", _ => null }; var rangeClause = string.Empty; if (queryRange != QueryRange.Forever) { var rangeFrom = queryRange switch { QueryRange.LastYear => DateTime.Now - TimeSpan.FromDays(365), QueryRange.LastMonth => DateTime.Now - TimeSpan.FromDays(30), QueryRange.LastWeek => DateTime.Now - TimeSpan.FromDays(7), _ => default }; rangeClause = $"AND i.Created >= \"{rangeFrom.ToString(Constants.CosmosDbDateTimeFormatString)}\""; } // get the complete list of ids var queryText = includeInactiveGalleries ? $"SELECT TOP @maxResults i.id AS Id, i.GalleryId AS PartitionKey FROM i WHERE (CONTAINS(i.Name, @term, true) OR CONTAINS(i.TagsCsv, @term, true)) {rangeClause} ORDER BY {orderClause}" : "NOT CURRENTLY SUPPORTED - NO WAY TO TELL!"; var queryDefinition = new QueryDefinition(queryText) .WithParameter("@maxResults", maxResults) .WithParameter("@term", term.ToLower()); var databaseIds = await Server.GetIdsByQueryAsync(Constants.ImagesContainerName, queryDefinition); // now with all the ids we know how many total results there are and so can populate paging info var pagedResultSet = new PagedResultSet <Image> { PageSize = pageSize, TotalResults = databaseIds.Count, CurrentPage = page }; // don't let users try and request a page that doesn't exist if (page > pagedResultSet.TotalPages) { page = pagedResultSet.TotalPages; } // now just retrieve a page's worth of images from the results var offset = (page - 1) * pageSize; var itemsToGet = databaseIds.Count >= pageSize ? pageSize : databaseIds.Count; // if we're on the last page just get the remaining items if (page == pagedResultSet.TotalPages) { itemsToGet = pagedResultSet.TotalResults - offset; } if (databaseIds.Count == 0) { return(pagedResultSet); } var pageIds = databaseIds.GetRange(offset, itemsToGet); // this is how we used to do it, and it used to be 3-5x slower //foreach (var id in pageIds) // pagedResultSet.Results.Add(await GetImageAsync(id.PartitionKey, id.Id)); var unorderedImages = new List <Image>(); var tasks = new List <Task>(); foreach (var pageId in pageIds) { tasks.Add(Task.Run(async() => { var i = await GetImageAsync(pageId.PartitionKey, pageId.Id); lock (unorderedImages) unorderedImages.Add(i); })); } var t = Task.WhenAll(tasks); t.Wait(); // put the unordered images into the results list in the same order as the ids were retrieved from the db foreach (var id in pageIds) { pagedResultSet.Results.Add(unorderedImages.SingleOrDefault(i => i.Id == id.Id)); } return(pagedResultSet); }
/// <summary> /// Returns a page of images with a specific tag /// </summary> /// <param name="tag">The tag used to find images for.</param> /// <param name="page">The page of galleries to return results from, for the first page use 1.</param> /// <param name="pageSize">The maximum number of galleries to return per page, i.e. 20.</param> /// <param name="maxResults">The maximum number of galleries to get paged results for, i.e. how many pages to look for.</param> /// <param name="querySortBy">How should we sort the search results?</param> /// <param name="queryRange">What time range should the search results cover?</param> public async Task <PagedResultSet <Image> > GetImagesForTagAsync( string tag, int page = 1, int pageSize = 20, int maxResults = 500, QuerySortBy querySortBy = QuerySortBy.DateCreated, QueryRange queryRange = QueryRange.Forever) { if (string.IsNullOrEmpty(tag)) { throw new ArgumentNullException(nameof(tag)); } if (pageSize < 1) { throw new ArgumentOutOfRangeException(nameof(pageSize), "pageSize must be a positive number"); } if (page < 1) { page = 1; } // limit page size to avoid incurring unnecessary charges and increasing latency if (pageSize > 100) { pageSize = 100; } // limit how big the id query is to avoid unnecessary charges and to keep latency within an acceptable range if (maxResults > 500) { maxResults = 500; } var orderClause = querySortBy switch { QuerySortBy.DateCreated => "i.Created DESC", QuerySortBy.Popularity => "i.Views DESC, i.Created DESC", QuerySortBy.Comments => "i.CommentCount DESC, i.Created DESC", _ => null }; var rangeClause = string.Empty; if (queryRange != QueryRange.Forever) { var rangeFrom = queryRange switch { QueryRange.LastYear => DateTime.Now - TimeSpan.FromDays(365), QueryRange.LastMonth => DateTime.Now - TimeSpan.FromDays(30), QueryRange.LastWeek => DateTime.Now - TimeSpan.FromDays(7), _ => default }; rangeClause = $"AND i.Created >= \"{rangeFrom.ToString(Constants.CosmosDbDateTimeFormatString)}\""; } // get the complete list of ids var query = $"SELECT TOP @maxResults i.id, i.GalleryId FROM i WHERE CONTAINS(i.TagsCsv, @tag, true) {rangeClause} ORDER BY {orderClause}"; var queryDefinition = new QueryDefinition(query).WithParameter("@maxResults", maxResults).WithParameter("@tag", tag); var container = Server.Instance.Database.GetContainer(Constants.ImagesContainerName); var queryResult = container.GetItemQueryIterator <JObject>(queryDefinition); var ids = new List <DatabaseId>(); double charge = 0; TimeSpan elapsedTime = default; while (queryResult.HasMoreResults) { var results = await queryResult.ReadNextAsync(); ids.AddRange(results.Select(result => new DatabaseId(result["id"].Value <string>(), result["GalleryId"].Value <string>()))); charge += results.RequestCharge; elapsedTime += results.Diagnostics.GetClientElapsedTime(); } Log.Debug($"ImageServer.GetImagesAsync(tag): Found {ids.Count} ids using query: {queryDefinition.QueryText}"); Log.Debug($"ImageServer.GetImagesAsync(tag): Total request charge: {charge}. Total elapsed time: {elapsedTime.TotalMilliseconds} ms"); // now with all the ids we know how many total results there are and so can populate paging info var pagedResultSet = new PagedResultSet <Image> { PageSize = pageSize, TotalResults = ids.Count, CurrentPage = page, QuerySortBy = querySortBy, QueryRange = queryRange }; if (page == 1 && pagedResultSet.TotalPages == 0) { return(pagedResultSet); } // don't let users try and request a page that doesn't exist if (page > pagedResultSet.TotalPages) { pagedResultSet.TotalResults = 0; pagedResultSet.Results.Clear(); return(pagedResultSet); } if (ids.Count <= 0) { return(pagedResultSet); } // now just retrieve a page's worth of images from the results var offset = (page - 1) * pageSize; var itemsToGet = ids.Count >= pageSize ? pageSize : ids.Count; // if we're on the last page just get the remaining items if (page == pagedResultSet.TotalPages) { itemsToGet = pagedResultSet.TotalResults - offset; } var pageIds = ids.GetRange(offset, itemsToGet); foreach (var id in pageIds) { pagedResultSet.Results.Add(await GetImageAsync(id.PartitionKey, id.Id)); } return(pagedResultSet); }