DynamoDB Scan di Go (AWS SDK v2)

NewScanPaginator adalah kursor, bukan koleksi: ia mulai dengan optimistis, berakhir kehabisan, dan mengambil ukuran halamannya dari tempat yang tidak diperlihatkan ScanInput di hadapan Anda. Untuk menghindari Scan sama sekali, lihat Query vs. Scan.

Kode

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
	ctx := context.TODO()
	cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
	if err != nil {
		log.Fatalf("load config: %v", err)
	}
	client := dynamodb.NewFromConfig(cfg)

	paginator := dynamodb.NewScanPaginator(client, &dynamodb.ScanInput{
		TableName:        aws.String("Music"),
		FilterExpression: aws.String("#filter0 >= :filterValue0"),
		ExpressionAttributeNames: map[string]string{
			"#filter0": "Year",
		},
		ExpressionAttributeValues: map[string]types.AttributeValue{
			":filterValue0": &types.AttributeValueMemberN{Value: "2010"},
		},
	})

	var items []map[string]types.AttributeValue
	for paginator.HasMorePages() {
		page, err := paginator.NextPage(ctx)
		if err != nil {
			log.Fatalf("scan: %v", err)
		}
		items = append(items, page.Items...)
	}
	fmt.Printf("Matched %d items\n", len(items))
}

Apa yang sebenarnya dikembalikan HasMorePages()

Terhadap fixture 600 lagu berukuran sekitar 3,9 KB per item, yang 8 di antaranya cocok dengan Year >= 2010 dan berada di urutan terakhir:

fresh HasMorePages():                    true    (before any request)
page 1: len(page.Items)=0  ScannedCount=271  CU=128.5  LastEvaluatedKey set
page 2: len(page.Items)=0  ScannedCount=271  CU=128.5  LastEvaluatedKey set
page 3: len(page.Items)=8  ScannedCount= 58  CU= 27.5  LastEvaluatedKey nil
exhausted HasMorePages():                false
NextPage() after exhaustion:             err = "no more pages available"

HasMorePages() bernilai true sebelum panggilan pertama, jadi loop-nya selalu berjalan setidaknya sekali. Anda tidak bisa memakainya untuk menguji apakah sebuah tabel kosong. Dua halaman lalu mengembalikan nol item sementara scan-nya masih berjalan, artinya if len(page.Items) == 0 { break } melaporkan hasil kosong pada tabel yang menyimpan 8 kecocokan. Dan paginator-nya sekali pakai: setelah loop, nilainya habis, dan NextPage mengembalikan error alih-alih memulai ulang. Melakukan scan lagi berarti memanggil NewScanPaginator lagi.

Limit ada di dua tempat, dan option-lah yang menang

Go membagi ukuran halaman antara struct input dan option milik paginator sendiri. Setel keduanya dan option yang diutamakan:

ScanInput.Limit = 500, ScanPaginatorOptions.Limit = 25  ->  ScannedCount 25

Menugaskan in.Limit = aws.Int32(500) lalu berharap halaman berisi 500 item adalah kekeliruan yang tak bersuara ketika sebuah functional option di tempat lain sudah menyetel 25. Kalau Anda hanya menyentuh ScanInput, paginator menghormatinya.

Diukur 2026-07-28 terhadap DynamoDB Local (amazon/dynamodb-local) dengan aws-sdk-go-v2/service/dynamodb v1.62.1 pada go1.26.5.

Penjelasan

  • page.Items bertipe []map[string]types.AttributeValue, bukan struct Anda. attributevalue.UnmarshalListOfMaps(items, &songs) mengonversi seluruh batch dalam satu panggilan dan mengubah Year menjadi int Go; tag struct dynamodbav yang mengendalikan pemetaannya.
  • Angka adalah string di jalur transport. Nilai mentahnya adalah &types.AttributeValueMemberN{Value: "2010"} — anggota N menyimpan string Go, jadi strconv berdiri di kedua sisi aritmetika apa pun kecuali Anda meng-unmarshal ke struct bertipe.
  • FilterExpression berjalan setelah pembacaan, dan itulah sebabnya dua halaman kosong itu tetap menghabiskan 128,5 unit masing-masing. Referensi API menyatakan dengan tegas bahwa pemfilteran "does not consume any additional read capacity units", dan konsekuensinya adalah ia juga tidak menghemat apa pun.
  • #filter0 itu wajib, bukan gaya-gayaan. Year adalah reserved word DynamoDB; tanpa alias ia mengembalikan ValidationException: Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: Year.
  • Segment / TotalSegments memberi tiap goroutine irisan tabelnya sendiri, dan masing-masing butuh paginator sendiri. Paralelisme memangkas wall clock dan menghabiskan kapasitas yang sama.

Lakukan secara visual

Query builder DynamoDB memancarkan bentuk program utuhnya — filter, map nama dan nilai, serta loop paginator — sehingga bagian yang diukur halaman ini dihasilkan, bukan diingat-ingat.

Untuk melihat berapa banyak item yang benar-benar disentuh sebuah filter sebelum Anda menjalankan scan-nya di layanan, unduh DynoTable dan jalankan terhadap tabelnya dalam sebuah grid.

Contoh terkait

Referensi

Bangun request ini secara visual

Susun operasi ini di DynamoDB Query Builder gratis — key condition, filter, index, Limit, urutan sortir, dan loop paginasi — lalu salin kembali sebagai program SDK v3, CLI, atau boto3 yang bisa dijalankan.

Buka DynamoDB Query Builder

Bekerja dengan DynamoDB tanpa Console

Klien desktop DynamoDB yang cepat dan menjalankan SQL sungguhan yang tidak bisa dijalankan DynamoDB — JOINs, GROUP BY, agregasi — dengan editing visual dan agen AI pada kunci Bedrock milik Anda sendiri.

Uji coba gratis 30 hari, tanpa kartu kredit — lalu paket Free tanpa batas waktu.