<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      基于.NetCore開發博客項目 StarBlog - (23) 文章列表接口分頁、過濾、搜索、排序

      前言

      上一篇留的坑,火速補上。

      在之前的第6篇中,已經有初步介紹,本文做一些補充,已經搞定這部分的同學可以快速跳過,基于.NetCore開發博客項目 StarBlog - (6) 頁面開發之博客文章列表

      對標準的WebApi來說,分頁、過濾、搜索、排序是很常見的功能,既可以方便用戶查看數據,又可以提升程序性能。

      通用請求參數

      定義一個類來作為通用的請求參數

      列表接口通用的參數是這幾個:PageSize, Page, Search, SortBy

      反映到URL上,就是 Blog/?pageSize=10&page=1&search=關鍵詞 這樣的形式

      public class QueryParameters {
          /// <summary>
          /// 最大頁面條目
          /// </summary>
          public const int MaxPageSize = 50;
      
          private int _pageSize = 10;
      
          /// <summary>
          /// 頁面大小
          /// </summary>
          public int PageSize {
              get => _pageSize;
              set => _pageSize = (value > MaxPageSize) ? MaxPageSize : value;
          }
      
          /// <summary>
          /// 當前頁碼
          /// </summary>
          public int Page { get; set; } = 1;
      
          /// <summary>
          /// 搜索關鍵詞
          /// </summary>
          public string? Search { get; set; }
      
          /// <summary>
          /// 排序字段
          /// </summary>
          public string? SortBy { get; set; }
      }
      

      文章列表請求參數

      在通用請求參數 QueryParameters 的基礎上,派生出文章列表的請求參數類 PostQueryParameters

      public class PostQueryParameters : QueryParameters {
          /// <summary>
          /// 僅請求已發布文章
          /// </summary>
          public bool OnlyPublished { get; set; } = false;
      
          /// <summary>
          /// 文章狀態
          /// </summary>
          public string? Status { get; set; }
          
          /// <summary>
          /// 分類ID
          /// </summary>
          public int CategoryId { get; set; } = 0;
      
          /// <summary>
          /// 排序字段
          /// </summary>
          public new string? SortBy { get; set; } = "-LastUpdateTime";
      }
      

      在通用請求參數的基礎上,增加文章相關的篩選字段。

      SortBy 字段使用 new 關鍵詞覆蓋基類屬性,設置為默認排序是最后更新時間,前面加個減號表示倒序。

      service

      StarBlog.Web/Services/PostService.cs 中封裝獲取分頁列表的方法

      代碼里有注釋,比較容易,根據 PostQueryParameters 中的各種參數來做過濾篩選

      public IPagedList<Post> GetPagedList(PostQueryParameters param) {
          var querySet = _postRepo.Select;
      
          // 是否發布
          if (param.OnlyPublished) {
              querySet = _postRepo.Select.Where(a => a.IsPublish);
          }
      
          // 狀態過濾
          if (!string.IsNullOrEmpty(param.Status)) {
              querySet = querySet.Where(a => a.Status == param.Status);
          }
      
          // 分類過濾
          if (param.CategoryId != 0) {
              querySet = querySet.Where(a => a.CategoryId == param.CategoryId);
          }
      
          // 關鍵詞過濾
          if (!string.IsNullOrEmpty(param.Search)) {
              querySet = querySet.Where(a => a.Title.Contains(param.Search));
          }
      
          // 排序
          if (!string.IsNullOrEmpty(param.SortBy)) {
              // 是否升序
              var isAscending = !param.SortBy.StartsWith("-");
              var orderByProperty = param.SortBy.Trim('-');
      
              querySet = querySet.OrderByPropertyName(orderByProperty, isAscending);
          }
      
          return querySet.Include(a => a.Category).ToList()
              .ToPagedList(param.Page, param.PageSize);
      }
      

      搜索的實現

      在上面 service 的代碼中

      可以看到搜索只是簡單的“關鍵詞過濾”

      使用 Title.Contains(param.Search) ,轉換成SQL就是

      select * from post where title like '%關鍵詞%'
      

      單純判斷標題字符串中是否包含有關鍵詞的子串。

      這對于簡單搜索一下文章是夠用的,如果要像谷歌、百度這類搜索引擎一樣能搜到文章的內容,需要用上全文檢索。

      現在主流的就是 ElasticSearch 和 Solr,后續可以考慮把這個功能加入本項目~

      PS:關于全文檢索,我之前寫過一篇文章:全文檢索引擎原理以及Lucene簡單介紹

      同時開源了一個玩具級的全文檢索引擎,https://github.com/Deali-Axy/CloverSearch

      分頁的實現

      本項目使用 X.PagedList 來實現分頁功能

      這個組件在結合MVC使用很方便,如果純WebApi的話,用數據庫自帶的分頁是更好的選擇,性能更好。

      這個分頁組件是在 IEnumerable<T> 上添加了擴展方法 ToPagedList,所以在用的時候要先把數據都讀取出來,再執行分頁,性能不如在數據庫里做好分頁再讀出來,很多ORM都支持這個功能,FreeSQL也不例外。

      用法例子:

      var list = fsql.Select<Topic>()
          .Where(a => a.Id > 10)
          .Count(out var total) //總記錄數量
          .Page(1, 20)
          .Tolist();
      

      詳情請查看FreeSQL官方文檔:https://freesql.net/guide/paging.html

      用上 X.PagedList 這個組件后,在任意 IEnumerable<T> 對象上執行 ToPagedList 方法,可以得到 IPagedList<T> 對象

      這個對象處理當前頁面的列表數據,還有分頁信息。

      為了讓前端可以方便的使用這部分信息,我又寫了個擴展方法。

      StarBlog.Web/Extensions/PagedListExt.cs

      public static class PagedListExt {
          public static PaginationMetadata ToPaginationMetadata(this IPagedList page) {
              return new PaginationMetadata {
                  PageCount = page.PageCount,
                  TotalItemCount = page.TotalItemCount,
                  PageNumber = page.PageNumber,
                  PageSize = page.PageSize,
                  HasNextPage = page.HasNextPage,
                  HasPreviousPage = page.HasPreviousPage,
                  IsFirstPage = page.IsFirstPage,
                  IsLastPage = page.IsLastPage,
                  FirstItemOnPage = page.FirstItemOnPage,
                  LastItemOnPage = page.LastItemOnPage
              };
          }
      
          public static string ToPaginationMetadataJson(this IPagedList page) {
              return JsonSerializer.Serialize(ToPaginationMetadata(page));
          }
      }
      

      這樣就可以在分頁后得到的 IPagedList 對象上執行 ToPaginationMetadata 得到分頁元數據了。

      這個 PaginationMetadata 也是本項目里定義的 ViewModel,StarBlog.Web/ViewModels/PaginationMetadata.cs

      代碼如下

      public class PaginationMetadata {
          public int PageCount { get; set; }
          public int TotalItemCount { get; set; }
          public int PageNumber { get; set; }
          public int PageSize { get; set; }
          public bool HasPreviousPage { get; set; }
          public bool HasNextPage { get; set; }
          public bool IsFirstPage { get; set; }
          public bool IsLastPage { get; set; }
          public int FirstItemOnPage { get; set; }
          public int LastItemOnPage { get; set; }
      }
      

      搞定

      controller與最終效果

      代碼如下

      [AllowAnonymous]
      [HttpGet]
      public ApiResponsePaged<Post> GetList([FromQuery] PostQueryParameters param) {
          var pagedList = _postService.GetPagedList(param);
          return new ApiResponsePaged<Post> {
              Message = "Get posts list",
              Data = pagedList.ToList(),
              Pagination = pagedList.ToPaginationMetadata()
          };
      }
      

      獲取到分頁數據之后,輸出 ApiResponsePaged<T> 類型的返回值

      這個也是我封裝的接口返回值類型,下一篇文章會詳細介紹

      Data 屬性就是列表數據,Pagination 屬性是分頁的信息。

      請求這個接口返回的效果如下

      {
        "pagination": {
          "pageCount": 40,
          "totalItemCount": 394,
          "pageNumber": 1,
          "pageSize": 10,
          "hasPreviousPage": false,
          "hasNextPage": true,
          "isFirstPage": true,
          "isLastPage": false,
          "firstItemOnPage": 1,
          "lastItemOnPage": 10
        },
        "statusCode": 200,
        "successful": true,
        "message": "Get posts list",
        "data": [{...},{...},{...},{...},{...}]
      }
      

      系列文章

      posted @ 2022-12-19 16:53  程序設計實驗室  閱讀(943)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久热久热中文字幕综合激情| 夜夜爽77777妓女免费看| 久久精品国产清自在天天线| 无码任你躁久久久久久久| 日韩亚av无码一区二区三区| 国产在线午夜不卡精品影院| 国产高潮国产高潮久久久| 99久久无色码中文字幕| 国产成人精品中文字幕| 亚洲人成网站999久久久综合| 亚欧洲乱码视频在线专区| 亚洲人成网站77777在线观看| 日韩精品国产另类专区| 爱啪啪精品一区二区三区| 日韩精品中文字幕有码| 国内少妇人妻偷人精品| 扒开粉嫩的小缝隙喷白浆视频| 亚洲人成人无码网WWW电影首页| 平阴县| 欧美z0zo人禽交另类视频| 久久精品国产精品亚洲艾| 亚洲成a人无码av波多野| 亚洲av成人午夜福利| 国产粉嫩学生高清专区麻豆| 国产免费视频一区二区| 韩国精品一区二区三区在线观看| 久久亚洲日本激情战少妇| 91精品国产福利尤物免费| 亚洲熟女精品一区二区| 国内精品视频区在线2021| 中文无码妇乱子伦视频| 日韩有码中文字幕av| 日韩区二区三区中文字幕| 久久精品蜜芽亚洲国产av| 午夜国产小视频| 国产超高清麻豆精品传媒麻豆精品| 国产精品欧美福利久久| 无码专区人妻系列日韩精品少妇| 日本喷奶水中文字幕视频| 成人一区二区不卡国产| 国产人妻精品午夜福利免费 |