Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
ページネーションをどう実装す るか
Slide 2
Slide 2 text
ページ番号・ベース (page: Int!, pageSize: Int!) カーソル・ベース (after: String, first: Int)
Slide 3
Slide 3 text
GraphQL Cursor Connections Specification https://relay.dev/graphql/connections.htm#sec- Connection-Types
Slide 4
Slide 4 text
No content
Slide 5
Slide 5 text
Cursor Connections では2つの観点が絡み合っている リソースAとリソースBの関係性を辿る ページネーション
Slide 6
Slide 6 text
リソースAとリソースBの関係性を辿る
Slide 7
Slide 7 text
Edge リソースAとリソースBのつながりを表現する中間的な型。
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
Edge が"2つのリソースの関係"がもつ情報をもたせるのに適 した場所になる。
Slide 10
Slide 10 text
補足: Connection が付加的な情報を持つこともある
Slide 11
Slide 11 text
ページネーション
Slide 12
Slide 12 text
Cursor Connections ではページ番号を使うのではなく、 起点となる Edge.cursor から範囲を指定してデータを取っ てくる。 after: "Y3Vyc29yMg==", first: 10 Y3Vyc29yMg== のカーソルをもつオブジェクトの次の10 件を取得 before: "Y3Vyc29yMg==", last: 10 Y3Vyc29yMg== のカーソルをもつオブジェクトの手前10 件を取得
Slide 13
Slide 13 text
メリット 整合性のあるページネーションが可能 次のページの先頭に、前のページの末尾と同じデータが入 る、ということがない 無限スクロールしていくようなUIに適している オフセットが大きい数字になった場合の LIMIT ... OFFSET ... が遅い問題から解放される
Slide 14
Slide 14 text
デメリット シーク法を用いたSQLは複雑性が増す(WHERE) 隣接していないページへのジャンプが難しい データの増減がページNのデータに影響して当然、という要 件には向かない ソート方法の種類に応じて、SQLのパターンが増える。
Slide 15
Slide 15 text
↓ 開発経験からして、大抵はこの要 件を持つような気がする。 (考えていないだけだけの可能性が大いに有。たとえばオートコンプリー トの類とか) データの増減がページNのデータに影響して当然、という要 件 これまでのB2B製品の
Slide 16
Slide 16 text
改めて ページネーションをどう実装す るか
Slide 17
Slide 17 text
リソースAとリソースBの関係性を辿る Cursor Connections の使用に則り、 Connection/Edge/Node の型を使うのが良さそう ページネーション ページ番号・ベースかカーソル・ベースか、設計時点で要 件を満たしつつ楽な方を実装すればよいのでは? ただし、将来的に実装しなかった方が欲しくなる可能性が あるので、両方の実装が共存できるようにしておきたい
Slide 18
Slide 18 text
例えば・・・
Slide 19
Slide 19 text
No content
Slide 20
Slide 20 text
命名規則(案) クエリ(フィールド) カーソル・ベース users ページ番号・ベース usersByPage ページ情報 カーソル・ベース CursorBasedPageInfo ページ番号・ベース PageBasedPageInfo
Slide 21
Slide 21 text
おまけ: UIにページネーションの機能がない場 合…
Slide 22
Slide 22 text
例えばフォルダー構造
Slide 23
Slide 23 text
階層構造×ページネーションというパターンは見たことがな い。
Slide 24
Slide 24 text
↓のような複雑なクエリからB/Eをどう守れば良いのか…
Slide 25
Slide 25 text
複雑性を用いたサーバー保護の観点からフォルダー一覧もペー ジネーションできるようにした方が良い。 pageSize の上限はシステムのフォルダー作成数上限と相 談してうまいこと決める 最悪、複数回リクエストすれば良い(Apollo Clientの fetchMore )
Slide 26
Slide 26 text
GraphQL スキーマ設計ガイド 第2版 安易な気持ちで tags: [Tag!]! という定義をルールに逆 らって作ってしまいました。すると Tag はいくつかのさら なる別の型への展開を持ち、ここで complexityの計算が崩 壊しました。教訓として、DBから1アクションで取れるリス トデータであっても、スカラ型でもenumでもない場合はイ ンメモリでCursor Connections相当の構造に変換するべき です。つらいです。
Slide 27
Slide 27 text
これなら安心して処理を拒否することができる。
Slide 28
Slide 28 text
これなら処理してあげても良いかもしれない…? (フォルダーごとに先頭3つの連絡先データを見せる)
Slide 29
Slide 29 text
と思ったが、やっぱり歪に見える。 階層ごとにページネーションが必要 全てのフォルダーに対して、子フォルダーを全て取得でき たかどうか気にしてあげる必要がある 複雑性を無駄に大きく見積もる必要がある
Slide 30
Slide 30 text
階層構造がネックになる場合、フラットなデータ構造に変更す ることも視野に入れる。
Slide 31
Slide 31 text
No content
Slide 32
Slide 32 text
シンプルになった。 その代わりに、F/Eがツリー構造を扱いたい場合には変換処理 を入れてもらうことになる。