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);
        }
示例#7
0
        /// <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);
        }
示例#8
0
        /// <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);
        }