Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Iteratorでページネーションを実現する
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
sonatard
September 24, 2024
Programming
1.4k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Iteratorでページネーションを実現する
sonatard
September 24, 2024
More Decks by sonatard
See All by sonatard
Shopifyアプリ開発における Shopifyの機能活用
sonatard
4
600
Goのエラースタックトレースの歴史と今後
sonatard
19
17k
Go 1.22のEnhanced ServeMux chiから移行できるのか?
sonatard
5
700
GraphQL実践ノウハウv2
sonatard
17
3.1k
プロトコル、インターフェースとしてのGraphQL
sonatard
4
2.3k
GraphQL実践ノウハウ/graphql-knowhow
sonatard
41
12k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Go1.18から導入されるnetip package/netip-package
sonatard
3
1.3k
Jetpack ComposeとGraphQLによるServer Driven UI/jetpackcompose-grahpql-serverdrivernui
sonatard
1
2k
Other Decks in Programming
See All in Programming
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.2k
Swiftのレキシカルスコープ管理
kntkymt
0
210
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
220
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
4
1.1k
TypeSpec で繋ぐ複数プロダクトの型安全
maroon8021
1
380
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
1.1k
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
500
AIエージェントと協働するCLI開発 — BunとOpenClawで学んだこと
yoshikouki
1
240
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
170
These Five Tricks Can Make Your Apps Greener, Cheaper, & Nicer
hollycummins
0
270
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
500
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
110
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Building Adaptive Systems
keathley
44
3k
How to train your dragon (web standard)
notwaldorf
97
6.7k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
GitHub's CSS Performance
jonrohan
1033
470k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Rails Girls Zürich Keynote
gr2m
96
14k
How to build a perfect <img>
jonoalderson
1
5.6k
Transcript
 1 *UFSBUPSͰϖʔδωʔγϣϯΛ࣮ݱ͢Δ (PͷΠςϨʔλਂງΓ/JHIU !TPOBUBSEͦͳଠגࣜձࣾ4UBDL
2 *UFSBUPSͷ͍ॴ w NBQ fi MUFSʜTMJDFपΓͰ͑ͦ͏ w ˠͳΜͱͳ͘Θ͔Δ w
ଞʹʁ
3 %#ͷϖʔδωʔγϣϯΛߟ͑ͯΈΔ w TQBOOFSDQBDLBHFͰ$MPVE4QBOOFSͷૢ࡞Λϥοϓ͍ͯ͠Δ w ҎԼ*UFSBUPSΛ͏લͷίʔυ cursorInfo = offset.NewCursorInfo() for
{ stmt := statement.ByCursor[domain.User](cursorInfo) users, pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if !pageInfo.HasNextPage { break } cursorInfo.Cursor = pageInfo.EndCursor }
4 cursorInfo := offset.NewCursorInfo() for { stmt := statement.ByCursor[domain.User](cursorInfo) users,
pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if !pageInfo.HasNextPage { break } cursorInfo.Cursor = pageInfo.EndCursor } ࣍ͷϖʔδ͕ͳ͚ΕGPS͔Βൈ͚Δ ࣍ͷϖʔδͷ$VSTPSΛߋ৽͢Δ
5 cursorInfo := offset.NewCursorInfo() for { stmt := statement.ByCursor[domain.User](cursorInfo) users,
pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if !pageInfo.HasNextPage { break } cursorInfo.Cursor = pageInfo.EndCursor } CSFBLΛΕͨΓɺ݅Λؒҧ͑Δ
6 cursorInfo := offset.NewCursorInfo() for { stmt := statement.ByCursor[domain.User](cursorInfo) users,
pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if !pageInfo.HasNextPage { break } // cursorInfo.Cursor = pageInfo.EndCursor } $VSTPSͷߋ৽ΛΕΔ
7 cursorInfo := offset.NewCursorInfo() for { stmt := statement.ByCursor[domain.User](cursorInfo) users,
pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if users.Invalid() { continue } if !pageInfo.HasNextPage { break } cursorInfo.Cursor = pageInfo.EndCursor } $VSTPSͷߋ৽ΛΕͯDPOUJOVF
8 cursorInfo := offset.NewCursorInfo() for { stmt := statement.ByCursor[domain.User](cursorInfo) users,
pageInfo, err := spannerc.GetMulti(ctx, stmt) if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if users.Invalid() { continue } if !pageInfo.HasNextPage { break } cursorInfo.Cursor = pageInfo.EndCursor } ࠓ·ͰՄೳͳൣғͰ-JOUͰରԠ͍ͯͨ͠
9 stmt := statement.ByCursor[domain.User](offset.NewCursorInfo()) for users, err := range spannerc.GetMultiIter(ctx,
stmt) { if err != nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if users.Invalid() { continue } } ϧʔϓͷϖʔδωʔγϣϯॲཧऴྃ݅ (FU.VMUJ*UFSʹӅṭ͞Ε͍ͯΔ 6TFSʹؔ࿈͢ΔॲཧͷΈΛॻ͚Α͘ͳͬͨ QBHF*OGPมͷΞΫηε͕ෆཁʹͳͬͨ
10 func GetMultiIter[T any](ctx context.Context, stmt offset.StatementWithCursor[T]) iter.Seq2[[]*T, error] {
return func(yield func([]*T, error) bool) { for { stmt.Statement.Params["offset"] = stmt.CursorInfo.Offset() ts, pageInfo, err := GetMulti[T](ctx, stmt) if !yield(ts, err) { return } if err != nil { return } if !pageInfo.HasNextPage { break } stmt.CursorInfo.Cursor = pageInfo.EndCursor } } } (FU.VMUJ*UFSͷ࣮
11 for users, err := range statement.ByCursor[domain.User](offset.NewCursorInfo()).All(ctx) { if err
!= nil { return nil, nil, fmt.Errorf(": %w", err) } // usersʹԿ͔͠Βͷॲཧ if users.Invalid() { continue } } ͓·͚ ͜Μͳ࣮ʹͨ͠ΒΑΓ(Pͷ*UFSBUPSΒ͍͠
12 *UFSBUPSͷ͍ॴ w ·ͱΊ w ϧʔϓΛநԽ͢Δ༻్Ͱ͑Δ w 'PSͷதͰ͋Δ݅ͰCSFBLDPOUJOVFΛ͍ͯ͠ΔͷͰ͋ΕγϯϓϧʹͰ͖Δ w Ͳ͜·Ͱ*UFSBUPSʹ͍ͯ͘͠ʁ
w *UFSBUPSײతʹಡΈͮΒ͍ͷͰɺͪΐͬͱͨ͜͠ͱͰ*UFSBUPSΛ͍͗͢Δͱٯʹ ίʔυ͕ಡΈͮΒ͘ͳΔ͔ w ϧʔϓʹ໌֬ͳ՝͕͋ΔɺͳॲཧΛ͍࣮ͭ͠ͳ͚ΕͳΒͳ͍߹ͳͲɺ ༻๏༻ྔΛकͬͯਖ਼͓͍͍ͩ͘͘͠͞ɻ
13 *UFSBUPSͷ͍ॴ w ͓·͚ w %BUBCBTFपลͰEBUBCBTFTRMQBDLBHFͳͲͰJP&0'ͳͲͷϋϯυϦϯά*UFSBUPS ͰෆཁʹͰ͖Δ w JP3FBEFSͳͲಉ༷ʁ w
͔͠͠JPQBDLBHFͷΠϯλʔϑΣʔε͕มΘΔͷ؆୯Ͱͳͦ͞͏ w ࠓޙඪ४ϥΠϒϥϦ͕ͲͷΑ͏ʹ*UFSBUPSʹରԠ͍͔ͯ͘͠ཁ