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
sonatard
September 24, 2024
Programming
1.5k
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
630
Goのエラースタックトレースの歴史と今後
sonatard
19
17k
Go 1.22のEnhanced ServeMux chiから移行できるのか?
sonatard
5
730
GraphQL実践ノウハウv2
sonatard
17
3.2k
プロトコル、インターフェースとしてのGraphQL
sonatard
4
2.4k
GraphQL実践ノウハウ/graphql-knowhow
sonatard
42
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
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
7
2.3k
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
360
初めての模倣学習とVLA
natsutan
0
490
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
210
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
640
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
450
自分的「カンファレンスの楽しみ方」
syumai
0
190
[KotlinConf Extended South Korea 2026] KotlinConf 2026 발표자 후기
wisemuji
0
100
業務時間外もAIに働いてもらう話
colorful12
3
10k
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
4.3k
PyConJP2026_wat_Python × Signal Processing: How to Draw Pictures with Sound Using Spectrogram Art
wat
0
670
Hello, Hiroshima Geospatial Data! — Exploring DoboX with Python
ra0kley
0
170
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
310
We Are The Robots
honzajavorek
0
340
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
sira's awesome portfolio website redesign presentation
elsirapls
0
400
Abbi's Birthday
coloredviolet
3
9.8k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.5k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Raft: Consensus for Rubyists
vanstee
141
7.7k
Mobile First: as difficult as doing things right
swwweet
225
10k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
Done Done
chrislema
186
16k
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ʹରԠ͍͔ͯ͘͠ཁ