現代のWebアプリケーションでは、大規模なデータセットを効率的に管理することが、パフォーマンスの最適化と優れたユーザーエクスペリエンスの提供において非常に重要です。この目的を達成するためのベストプラクティスの1つが、Web APIにリモートページングを実装し、クライアントが必要なデータだけをリクエストして取得できるようにすることです。
この記事では、Web APIを拡張してリモートページング機能をサポートし、Ignite UIのigxGridコンポーネントやリモートデータを利用できるその他のコンポーネントとシームレスに統合する方法について説明します。
それでは、これがどのように機能するのか、具体的なポイントを見ていきましょう。
- 『 OData 』仕様のベスト プラクティスに基づいて Web API を拡張する理由
- 『 OData 』 仕様
- スキップ / トップ アプローチとページインデックス / サイズ アプローチの違い
- OrderBy をサポートするためのサービスの拡張
- igxGridでのリモートページングは、どのように機能しますか?
- 『 App Builder 』でグリッドのリモートページングを構成する方法
- 結論
『 OData 』仕様のベスト プラクティスに基づいて Web API を拡張する理由
この記事で紹介するコードでは、『 OData 』の特性をいくつか活用していることにお気づきになるでしょう。特に、ページネーションやソートのクエリパラメータを処理する点が挙げられます。ただし、これに加え、従来の『 OData 』 実装を超える要素も取り入れています。
なぜ『 OData 』 を選ぶのでしょうか? OData(Open Data Protocol)は、RESTful APIを構築・利用するための標準化されたフレームワークです。この仕様を採用することで、異なるアプリケーション間の通信がスムーズになり、システム間の統合が容易(標準化)になり、特にエンタープライズ環境での運用に適しています。
さらに、『 OData 』の豊富なクエリ機能を活用することで、クライアント側でデータのフィルタリング、並べ替え、ページングを行えるため、サーバーコードに変更を加える必要がありません。これにより、柔軟性が大幅に向上します。また、『 OData 』はJSONやXMLといったさまざまなデータ形式に対応しており、多様なデータソースをサポートします。
『 OData 』 仕様
『 OData 』仕様では、個別のエンドポイント(例: GetCustomersWithSkip や GetCustomersWithPage)を用いることで、異なるページングスタイル(スキップ/トップ/ページインデックス/サイズ)を実装することができます。しかし、『 OData 』は通常、クエリパラメーターを受け入れる1つの統合エンドポイントを提供し、より標準化されたインターフェイスを実現します。
OData v3では、データへの個別のリクエストに加え、合計レコード数が同じオブジェクト結果内で提供される仕組みを採用しています。これにより、データ取得とレコードの全体数の確認が統一された形で行えます。
以下は、ODataで利用可能な関連エンドポイントの例です。
- SkipとTopを使用したデータのフェッチ:このエンドポイントは、指定した数のレコードをスキップしたうえで、必要なデータのサブセット(特定の範囲のデータ)を取得します。
- インラインカウントを含む同じオブジェクト結果:1回のクエリで、データセットに加え、全体のレコード数も返します。これにより、追加のリクエストを行わずに、データ全体の把握が可能です。
- Total Count専用のURL:データ自体ではなく、製品やレコードの総数のみを取得するためのエンドポイントです。
OData v4では、合計レコード数を同じオブジェクト結果の一部として提供するだけでなく、別のリクエストを通じてデータを取得する機能も引き続きサポートしています。
- $skip:指定した数のレコードをスキップして、その後のデータを取得します。
- システムクエリオプション($top および $skip):データを取得する範囲を指定することができます。
GET https://services.odata.org/TripPinRESTierService/People?$top=2 GET https://services.odata.org/TripPinRESTierService/People?$skip=18
- システムクエリオプション($top および $skip):合計数を個別に取得します。 詳細については、OData v4 のドキュメントを参照してください。
スキップ / トップ アプローチとページインデックス / サイズ アプローチの違い
リモートページングを効果的に実装するためには、スキップ / トップ アプローチとページインデックス / サイズ アプローチの違いを理解することが重要です。 それぞれの特徴とユースケースを以下に説明します。
スキップ / トップ アプローチ
- スキップ(Skip): データ取得(フェッチ)を開始する前に、スキップするレコードの数を指定します。
- トップ(Top): 取得(フェッチ)するレコードの最大数を指定します。
- ユースケース: クライアント側でページングを明示的に制御するシナリオで使用され、合計ページ数(ページング)を計算する必要がない場合に適しています。
var pagedResult = pagingService.FetchPagedData<CustomerDb, CustomerDto>( customers, skip: 10, top: 20, orderBy: "CustomerName asc");
ページインデックス / サイズ アプローチ
- ページインデックス(Page Index):現在のページを示します(通常、0ベースインデックスを使用します)。
- サイズ(Size): 1ページあたりに返されるレコードの数を指定します。
- ユースケース:「ページごとにデータを取得する」という設計に馴染み、ページングの概念が直感的で、ユーザーにとって扱いやすいシナリオに適しています。
var pagedResult = pagingService.FetchPagedData<CustomerDb, CustomerDto>( customers, pageIndex: 1, size: 20, orderBy: "CustomerName asc");
OrderBy をサポートするためのサービスの拡張
APIをさらに強化するには、結果の並べ替え(OrderBy)をサポートするように拡張することを検討してください。そのためには、リクエストにorderByパラメータを追加して、並べ替え対象となるフィールドと並べ替えの方向(昇順/降順)を指定します。クライアントは柔軟にデータを操作できるようになり、ユーザーエクスペリエンスが大幅に向上します。
コード例:
[HttpGet("GetCustomersWithOrderBy")] public ActionResult<PagedResultDto<CustomerDto>> GetCustomersWithOrderBy( [FromQuery][Attributes.SwaggerOrderByParameter] string? orderBy) { try { var customers = this.customerService.GetAllAsQueryable(); var pagedResult = pagingService.FetchPagedData<CustomerDb, CustomerDto>(customers, orderBy: orderBy); return Ok(pagedResult); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
igxGridでのリモートページングは、どのように機能しますか?
まず、Ignite UIは、高性能でデータが豊富なスケーラブルなWebアプリケーションを構築するための完全なUIコンポーネントライブラリです。
- 市場最速のAngularデータグリッド(igxGrid)
- 120種類以上の高性能チャート
- 階層グリッド、複数行レイアウト、高度なフィルタリングなどの高度なコントロールと機能
これにより、データに特化したアプリケーションの開発が効率的に行えます。詳細については、弊社のAngularコンポーネントを他のベンダーのコンポーネントと比較することも可能です。
また、Ignite UIのigxGridコンポーネントは、リモートページングとシームレスに連携するよう設計されています。ユーザーがグリッド内のページを移動する際、必要なデータを動的にフェッチします。このアプローチにより、必要なレコードのみを読み込み、無駄なデータ転送を削減します。
適切に構成されている場合、igxGrid は、APIベースのデータ取得設計に基づいて、スキップ / トップアプローチ または ページ インデックス / サイズアプローチ に基づいて、特定のページデータを要求します。
『 Ignite UI for Angular のData Grid 』 のリモート ページングの詳細については、こちらを参照してください。
component.ts
public ngAfterViewInit() { // Initialize Grid this.grid1.isLoading = true; this.data$ = this.northwindService.remoteData$; this.totalRecords$ = this.northwindService.dataLength$; // Load Grid data this.paginateGrid(); this.data$.pipe(takeUntil(this.destroy$)).subscribe(() => { this.isLoading = false; }); ...
public paginateGrid() { this.isLoading = true; const { skip, top } = this.calculatePagination(this.grid1.page, this._perPage); this.northwindService.getData(skip, top); }
private calculatePagination(page: number, perPage: number) { const skip = page * perPage; const top = perPage; return { skip, top }; }
こちらはAngularのリモートサービスに関連するコードサンプルです。
このデモアプリケーションでは、Angularのリモートサービスとページングの動作を確認できます。
そして、詳細なコードについてはGitHubリポジトリをご確認ください。
『 App Builder 』でグリッドのリモートページングを構成する方法
App Builderは、モダンなWebアプリを構築するためのクラウドベースのローコードプラットフォームであり、リモートページングを簡単かつ迅速に構成できる新機能が追加されました。 このツールは、以下の特徴を持つ強力な開発環境を提供します。
- ドラッグ&ドロップの直感的な操作性
- 60種類以上のUIコンポーネントを搭載
- Indigo.Designとの統合により、シームレスなデータバインディングと完全なデザインシステムを提供
- 開発時間を最大80%削減
- SketchやFigmaのデザインファイル、またはゼロから構築したアプリから、ワンクリックでAngular、Blazor、Web Components、Reactのクリーンで本番対応可能なコードを生成
App Builder でリモートページングを構成する手順を次に示します。
- リモートページングモードの選択::グリッド構成画面で、リモートページングを有効にします。
- API エンドポイントの設定:データ取得および合計レコード数を取得するためのエンドポイントを指定します。
- クエリパラメータの定義:ページングに必要なクエリパラメータ (例:skip、top、pageIndex、size など) を設定します。
- グリッドをデータにバインド:グリッドを返されたデータコンテキストに接続し、ページングされたデータが反映されるようにします。
さらに詳細な設定方法については、App Builderの公式ドキュメントをご参照ください。
結論
バックエンドサービスをIgnite UIのigxGridと統合し、リモートページングを実装することで、Webアプリケーションのパフォーマンスとユーザビリティを大幅に向上させることができます。さらに、OData標準を活用し、Web APIを適切に構成することで、大規模なデータセットを扱うユーザーに対してシームレスなエクスペリエンスを提供可能です。
この設定により、データの読み込み時間を短縮するだけでなく、データへのアクセス方法や表示形式に柔軟性を持たせることができ、より直感的で効率的な操作を実現します。
この記事の原文は以下よりご確認いただけます。 [Katie Mikova(https://www.infragistics.com/community/blogs/b/infragistics/posts/backend-services-in-angular-grid) (ズドラフコ・コレフ) / 2024年11月25日(月)