public static async Task <PagedResult <Remark> > QueryAsync(this IMongoCollection <Remark> remarks, BrowseRemarks query) { if (!query.IsLocationProvided() && query.AuthorId.Empty() && query.ResolverId.Empty()) { query.Latest = true; } if (query.Page <= 0) { query.Page = 1; } if (query.Results <= 0) { query.Results = 10; } if (query.Results > 1000) { query.Results = 1000; } var filterBuilder = new FilterDefinitionBuilder <Remark>(); var filter = FilterDefinition <Remark> .Empty; if (query.IsLocationProvided() && !query.SkipLocation) { var maxDistance = query.Radius > 0 ? (double?)query.Radius / 1000 / 6378.1 : null; filter = filterBuilder.NearSphere(x => x.Location, query.Longitude, query.Latitude, maxDistance); } if (query.AuthorId.NotEmpty()) { filter = filter & filterBuilder.Where(x => x.Author.UserId == query.AuthorId); if (query.OnlyLiked) { filter = filter & filterBuilder.Where(x => x.Votes.Any(v => v.UserId == query.AuthorId && v.Positive)); } else if (query.OnlyDisliked) { filter = filter & filterBuilder.Where(x => x.Votes.Any(v => v.UserId == query.AuthorId && !v.Positive)); } } if (query.ResolverId.NotEmpty()) { filter = filter & filterBuilder.Where(x => x.State.State == "resolved" && x.State.User.UserId == query.ResolverId); } if (!query.Description.Empty()) { filter = filter & filterBuilder.Where(x => x.Description.Contains(query.Description)); } if (query.Categories?.Any() == true) { filter = filter & filterBuilder.Where(x => query.Categories.Contains(x.Category.Name)); } if (query.Tags?.Any() == true) { filter = filter & filterBuilder.Where(x => x.Tags.Any(y => query.Tags.Contains(y))); } if (query.States?.Any() == true) { filter = filter & filterBuilder.Where(x => query.States.Contains(x.State.State)); } if (!query.Disliked) { filter = filter & filterBuilder.Where(x => x.Rating > NegativeVotesThreshold); } if (query.GroupId.HasValue && query.GroupId != Guid.Empty) { filter = filter & filterBuilder.Where(x => x.Group.Id == query.GroupId); } if (query.UserFavorites.NotEmpty()) { filter = filterBuilder.Where(x => x.UserFavorites.Contains(query.UserFavorites)); } var totalCount = await remarks.CountAsync(_ => true); var filteredRemarks = remarks.Find(filter); var totalPages = (int)totalCount / query.Results + 1; var findResult = filteredRemarks .Skip(query.Results * (query.Page - 1)) .Limit(query.Results); findResult = SortRemarks(query, findResult); var result = await findResult.ToListAsync(); return(PagedResult <Remark> .Create(result, query.Page, query.Results, totalPages, totalCount)); }