$30 off During Our Annual Pro Sale. View Details »

Iteratorでページネーションを実現する

sonatard
September 24, 2024

 Iteratorでページネーションを実現する

sonatard

September 24, 2024
Tweet

More Decks by sonatard

Other Decks in Programming

Transcript

  1. 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 }
  2. 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Λߋ৽͢Δ
  3. 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Λ๨ΕͨΓɺ৚݅Λؒҧ͑Δ
  4. 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ͷߋ৽Λ๨ΕΔ
  5. 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
  6. 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ͰରԠ͍ͯͨ͠
  7. 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ม਺΁ͷΞΫηε͕ෆཁʹͳͬͨ
  8. 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ͷ࣮૷
  9. 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Β͍͠
  10. 12 *UFSBUPSͷ࢖͍ॴ w ·ͱΊ w ϧʔϓΛந৅Խ͢Δ༻్Ͱ࢖͑Δ w 'PSͷதͰ͋Δ৚݅ͰCSFBL΍DPOUJOVFΛ͍ͯ͠ΔͷͰ͋Ε͹γϯϓϧʹͰ͖Δ w Ͳ͜·Ͱ*UFSBUPSʹ͍ͯ͘͠ʁ

    w *UFSBUPS͸௚ײతʹಡΈͮΒ͍ͷͰɺͪΐͬͱͨ͜͠ͱͰ*UFSBUPSΛ࢖͍͗͢Δͱٯʹ ίʔυ͕ಡΈͮΒ͘ͳΔ͔΋ w ϧʔϓʹ໌֬ͳ՝୊͕͋Δɺ৑௕ͳॲཧΛ͍ͭ΋࣮૷͠ͳ͚Ε͹ͳΒͳ͍৔߹ͳͲɺ ༻๏༻ྔΛकͬͯਖ਼͓͘͠࢖͍͍ͩ͘͞ɻ
  11. 13 *UFSBUPSͷ࢖͍ॴ w ͓·͚ w %BUBCBTFपลͰ͸EBUBCBTFTRMQBDLBHFͳͲͰJP&0'ͳͲͷϋϯυϦϯά΋*UFSBUPS ͰෆཁʹͰ͖Δ w JP3FBEFSͳͲ΋ಉ༷ʁ w

    ͔͠͠JPQBDLBHFͷΠϯλʔϑΣʔε͕มΘΔͷ͸؆୯Ͱ͸ͳͦ͞͏ w ࠓޙඪ४ϥΠϒϥϦ͕ͲͷΑ͏ʹ*UFSBUPSʹରԠ͍͔ͯ͘͠΋ཁ஫໨