### Put and Get DynamoDB Item Source: https://github.com/guregu/dynamo/blob/master/README.md Demonstrates how to put a new item into a DynamoDB table and then retrieve the same item using its keys. ```go // put item w := widget{UserID: 613, Time: time.Now(), Msg: "hello"} err = table.Put(w).Run(ctx) // get the same item var result widget err = table.Get("UserID", w.UserID). Range("Time", dynamo.Equal, w.Time). One(ctx, &result) ``` -------------------------------- ### Conditional Delete with Expression Source: https://context7.com/guregu/dynamo/llms.txt Perform a conditional delete operation using 'If' to specify conditions that must be met. This example combines 'begins_with' and attribute name placeholders. ```go err := table.Delete("ID", 42). If("'Status' = ? AND begins_with($, ?)", "pending", "Name", "Test"). Run(ctx) ``` -------------------------------- ### Batch Get Items API Source: https://context7.com/guregu/dynamo/llms.txt Retrieves multiple items from one or more tables in a single request. More efficient than individual Get requests for bulk reads. ```APIDOC ## Batch Get Items ### Description Retrieves multiple items from one or more tables in a single request. More efficient than individual Get requests for bulk reads. ### Method GET (Conceptual - actual implementation uses SDK methods) ### Endpoint N/A (SDK-based operation) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (Operation is defined by SDK method calls) ### Request Example ```go // Batch get with hash key only var widgets []Widget err := widgetsTable.Batch("ID").Get(dynamo.Keys{1}, dynamo.Keys{2}, dynamo.Keys{42}).All(ctx, &widgets) // Batch get with hash and range key var events []Event err = db.Table("Events").Batch("UserID", "Date").Get(dynamo.Keys{1, "2024-01-15"}, dynamo.Keys{1, "2024-01-16"}, dynamo.Keys{2, "2024-01-15"}).All(ctx, &events) // Batch get with projection err = widgetsTable.Batch("ID").Get(dynamo.Keys{1}, dynamo.Keys{2}).Project("ID", "Name").All(ctx, &widgets) // Consistent read err = widgetsTable.Batch("ID").Get(dynamo.Keys{1}, dynamo.Keys{2}).Consistent(true).All(ctx, &widgets) // Batch get from multiple tables widgetBatch := widgetsTable.Batch("ID").Get(dynamo.Keys{1}, dynamo.Keys{2}) sprocketBatch := sprocketsTable.Batch("PartID").Get(dynamo.Keys{"A1"}, dynamo.Keys{"B2"}) // Merge batches and iterate with table tracking var tableName string iter := widgetBatch.Merge(sprocketBatch).IterWithTable(&tableName) var item map[string]interface{}/ for iter.Next(ctx, &item) { log.Printf("Table: %s, Item: %+v", tableName, item) } ``` ### Response #### Success Response (200) - **items** ([]interface{}) - A list of retrieved items. The structure depends on the projection and table schemas. #### Response Example ```json // Example for a batch get of widgets: [ { "ID": 1, "Name": "Widget A" }, { "ID": 2, "Name": "Widget B" } ] // Example for merged batch get from multiple tables: { "tableName": "Widgets", "item": { "ID": 1, "Name": "Widget A" } } { "tableName": "Sprockets", "item": { "PartID": "A1", "Size": 10 } } ``` ``` -------------------------------- ### Define UserAction Struct with DynamoDB Keys and Indexes Source: https://github.com/guregu/dynamo/blob/master/README.md Use struct tags to specify hash keys, range keys, and global/local secondary indexes when creating a DynamoDB table. This example defines a UserAction struct with various key and index configurations. ```go type UserAction struct { UserID string `dynamo:"ID,hash" index:"Seq-ID-index,range" Time time.Time `dynamo:",range" Seq int64 `localIndex:"ID-Seq-index,range" index:"Seq-ID-index,hash" UUID string `index:"UUID-index,hash" } ``` -------------------------------- ### Track Consumed Capacity for Get Operation Source: https://context7.com/guregu/dynamo/llms.txt Use the ConsumedCapacity method to track the RCU consumed by a Get operation. This is useful for monitoring and optimizing read throughput. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash"` Name string } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") // Track consumed capacity for a Get var cc dynamo.ConsumedCapacity var widget Widget err := table.Get("ID", 42). ConsumedCapacity(&cc). One(ctx, &widget) if err != nil { log.Fatal(err) } log.Printf("Get consumed: %.2f RCU", cc.Total) // Track capacity for a Scan with metrics var sm dynamo.ScanMetrics cc = dynamo.ConsumedCapacity{} // Reset var widgets []Widget err = table.Scan(). Filter("'Name' = ?", "Test"). ConsumedCapacity(&cc). ScanMetrics(&sm). All(ctx, &widgets) if err != nil { log.Fatal(err) } log.Printf("Scan consumed: %.2f RCU", cc.Total) log.Printf("Items scanned: %d", sm.Scanned) log.Printf("Items returned: %d", sm.Count) log.Printf("API requests: %d", cc.Requests) // Track capacity for Put cc = dynamo.ConsumedCapacity{} err = table.Put(Widget{ID: 100, Name: "New"}). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Put consumed: %.2f WCU", cc.Total) // Track capacity for Update cc = dynamo.ConsumedCapacity{} err = table.Update("ID", 100). Set("Name", "Updated"). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Update consumed: %.2f WCU", cc.Total) // Track capacity for BatchWrite cc = dynamo.ConsumedCapacity{} _, err = table.Batch("ID").Write(). Put(Widget{ID: 1, Name: "A"}, Widget{ID: 2, Name: "B"}). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Batch write consumed: %.2f WCU", cc.Total) // Track capacity for transactions cc = dynamo.ConsumedCapacity{} err = db.WriteTx(). Put(table.Put(Widget{ID: 200, Name: "Tx1"})). Put(table.Put(Widget{ID: 201, Name: "Tx2"})). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Transaction consumed: %.2f WCU (Read: %.2f, Write: %.2f)", cc.Total, cc.Read, cc.Write) // Detailed capacity breakdown log.Printf("Table capacity: %.2f", cc.Table) for name, cap := range cc.GSI { log.Printf("GSI %s capacity: %.2f", name, cap) } for name, cap := range cc.LSI { log.Printf("LSI %s capacity: %.2f", name, cap) } } ``` -------------------------------- ### Scan using begins_with Function Source: https://context7.com/guregu/dynamo/llms.txt Utilize DynamoDB functions within filter expressions. 'begins_with' checks if a string attribute starts with a specified prefix. ```go err := table.Scan(). Filter("begins_with('Name', ?)", "Widget"). All(ctx, &widgets) ``` -------------------------------- ### Using AWS SDK Encoding with DynamoDB Go Library Source: https://github.com/guregu/dynamo/blob/master/README.md Wrap objects with dynamo.AWSEncoding to use the official AWS SDK's encoding facilities. When getting an item, pass a pointer to AWSEncoding. ```go // Notice the use of the dynamodbav struct tag type book struct { ID int `dynamodbav:"id"` Title string `dynamodbav:"title"` } // Putting an item err := db.Table("Books").Put(dynamo.AWSEncoding(book{ ID: 42, Title: "Principia Discordia", })).Run(ctx) // When getting an item you MUST pass a pointer to AWSEncoding! var someBook book err := db.Table("Books").Get("ID", 555).One(ctx, dynamo.AWSEncoding(&someBook)) ``` -------------------------------- ### Batch Get Items from DynamoDB Source: https://context7.com/guregu/dynamo/llms.txt Efficiently retrieve multiple items from one or more DynamoDB tables in a single request. Supports hash and range keys, projections, and consistent reads. Can merge batches from different tables. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash" Name string } type Sprocket struct { PartID string `dynamo:"PartID,hash" Size int } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) widgetsTable := db.Table("Widgets") sprocketsTable := db.Table("Sprockets") // Batch get with hash key only var widgets []Widget err := widgetsTable.Batch("ID"). Get(dynamo.Keys{1}, dynamo.Keys{2}, dynamo.Keys{42}). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Batch get with hash and range key type Event struct { UserID int `dynamo:"UserID,hash" Date string `dynamo:",range" Action string } var events []Event err = db.Table("Events").Batch("UserID", "Date"). Get( dynamo.Keys{1, "2024-01-15"}, dynamo.Keys{1, "2024-01-16"}, dynamo.Keys{2, "2024-01-15"}, ). All(ctx, &events) if err != nil { log.Fatal(err) } // Batch get with projection err = widgetsTable.Batch("ID"). Get(dynamo.Keys{1}, dynamo.Keys{2}). Project("ID", "Name"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Consistent read err = widgetsTable.Batch("ID"). Get(dynamo.Keys{1}, dynamo.Keys{2}). Consistent(true). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Batch get from multiple tables widgetBatch := widgetsTable.Batch("ID").Get(dynamo.Keys{1}, dynamo.Keys{2}) sprocketBatch := sprocketsTable.Batch("PartID").Get(dynamo.Keys{"A1"}, dynamo.Keys{"B2"}) // Merge batches and iterate with table tracking var tableName string iter := widgetBatch.Merge(sprocketBatch).IterWithTable(&tableName) var item map[string]interface{} for iter.Next(ctx, &item) { log.Printf("Table: %s, Item: %+v", tableName, item) } if err := iter.Err(); err != nil { log.Fatal(err) } log.Printf("Retrieved %d widgets", len(widgets)) } ``` -------------------------------- ### Custom Marshaling and Unmarshaling in Go Source: https://context7.com/guregu/dynamo/llms.txt Implement `Marshaler` and `Unmarshaler` interfaces for custom types to control how they are converted to and from DynamoDB attribute values. This example shows custom handling for a `Status` enum. ```go package main import ( "log" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/guregu/dynamo/v2" ) // Custom type implementing Marshaler/Unmarshaler type Status int const ( StatusPending Status = iota StatusActive StatusCompleted ) func (s Status) MarshalDynamo() (types.AttributeValue, error) { var str string switch s { case StatusPending: str = "PENDING" case StatusActive: str = "ACTIVE" case StatusCompleted: str = "COMPLETED" } return &types.AttributeValueMemberS{Value: str}, nil } func (s *Status) UnmarshalDynamo(av types.AttributeValue) error { str, ok := av.(*types.AttributeValueMemberS) if !ok { return nil } switch str.Value { case "PENDING": *s = StatusPending case "ACTIVE": *s = StatusActive case "COMPLETED": *s = StatusCompleted } return nil } type Widget struct { ID int Name string Status Status } func main() { // Marshal a struct to DynamoDB item widget := Widget{ID: 1, Name: "Test", Status: StatusActive} item, err := dynamo.MarshalItem(widget) if err != nil { log.Fatal(err) } log.Printf("Marshaled item: %+v", item) // Unmarshal item back to struct var decoded Widget err = dynamo.UnmarshalItem(item, &decoded) if err != nil { log.Fatal(err) } log.Printf("Decoded widget: %+v", decoded) // Marshal single value av, err := dynamo.Marshal(42) if err != nil { log.Fatal(err) } log.Printf("Marshaled value: %+v", av) // Unmarshal single value var num int err = dynamo.Unmarshal(av, &num) if err != nil { log.Fatal(err) } log.Printf("Unmarshaled number: %d", num) // Use AWS encoding for compatibility with official SDK type Book struct { ID int `dynamodbav:"id"` Title string `dynamodbav:"title"` } // Wrap with AWSEncoding to use dynamodbav tags book := Book{ID: 42, Title: "The Guide"} _ = dynamo.AWSEncoding(book) // Use this in Put/Get operations } ``` -------------------------------- ### Get Old Item Value Before Update in Go Source: https://context7.com/guregu/dynamo/llms.txt Updates the 'Count' attribute and retrieves the item's state *before* the update was applied into the 'old' variable. ```go var old Widget err = table.Update("ID", 42). Set("Count", 300). OldValue(ctx, &old) if err != nil { log.Fatal(err) } log.Printf("Old widget: %+v", old) ``` -------------------------------- ### Get Updated Item Value in Go Source: https://context7.com/guregu/dynamo/llms.txt Updates the 'Count' attribute and retrieves the item's new state after the update into the 'updated' variable. ```go var updated Widget err = table.Update("ID", 42). Set("Count", 200). Value(ctx, &updated) if err != nil { log.Fatal(err) } log.Printf("Updated widget: %+v", updated) ``` -------------------------------- ### Get DynamoDB Item by Primary Key Source: https://context7.com/guregu/dynamo/llms.txt Retrieves a single item using its primary key. Supports projections and strongly consistent reads. Ensure the Widget struct and table are correctly defined. ```go package main import ( "context" "log" "time" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash" Timestamp time.Time `dynamo:",range" Name string Count int } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") var widget Widget timestamp := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC) // Get item with hash key only err := table.Get("ID", 42).One(ctx, &widget) if err == dynamo.ErrNotFound { log.Println("Item not found") return } if err != nil { log.Fatal(err) } // Get item with hash and range key err = table.Get("ID", 42). Range("Timestamp", dynamo.Equal, timestamp). One(ctx, &widget) if err != nil { log.Fatal(err) } // Get with projection (only fetch specific attributes) err = table.Get("ID", 42). Range("Timestamp", dynamo.Equal, timestamp). Project("Name", "Count"). One(ctx, &widget) if err != nil { log.Fatal(err) } // Strongly consistent read err = table.Get("ID", 42). Range("Timestamp", dynamo.Equal, timestamp). Consistent(true). One(ctx, &widget) if err != nil { log.Fatal(err) } log.Printf("Widget: %+v", widget) } ``` -------------------------------- ### Get Current Value on Condition Failure in Go Source: https://context7.com/guregu/dynamo/llms.txt Attempts to update 'Status' if 'Status' is 'processing'. If the condition fails, it retrieves and logs the item's current state without performing the update. ```go wrote, err := table.Update("ID", 42). Set("Status", "completed"). If("'Status' = ?", "processing"). CurrentValue(ctx, &updated) if err != nil { log.Fatal(err) } if !wrote { log.Printf("Condition failed, current value: %+v", updated) } ``` -------------------------------- ### Configure AWS SDK with DynamoDB Transaction Conflict Retries Source: https://github.com/guregu/dynamo/blob/master/README.md Configure the AWS SDK to automatically retry on transaction conflicts using `dynamo.RetryTxConflicts`. This is useful for ensuring transactional integrity in DynamoDB operations. The example demonstrates loading default AWS configuration with a custom retryer. ```go import ( "context" "log" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) func main() { cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRetryer(func() aws.Retryer { return retry.NewStandard(dynamo.RetryTxConflicts) })) if err != nil { log.Fatal(err) } db := dynamo.New(cfg) // use db } ``` -------------------------------- ### Initialize DynamoDB Client and Table Source: https://github.com/guregu/dynamo/blob/master/README.md Load AWS SDK configuration and create a DynamoDB client instance, then obtain a reference to a specific table. ```go cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-east-1")) if err != nil { log.Fatalf("unable to load SDK config, %v", err) } db := dynamo.New(cfg) table := db.Table("Widgets") ``` -------------------------------- ### Create DynamoDB Client Source: https://context7.com/guregu/dynamo/llms.txt Initializes a dynamo DB client using AWS SDK v2 configuration. This client is essential for all subsequent DynamoDB operations. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) func main() { ctx := context.Background() // Load AWS configuration from environment/credentials cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) if err != nil { log.Fatalf("unable to load SDK config: %v", err) } // Create dynamo client db := dynamo.New(cfg) // Get a table reference table := db.Table("MyTable") // List all tables tables, err := db.ListTables().All(ctx) if err != nil { log.Fatal(err) } log.Printf("Tables: %v", tables) } ``` -------------------------------- ### Delete and Describe DynamoDB Table with Go Source: https://context7.com/guregu/dynamo/llms.txt This Go code demonstrates how to describe a DynamoDB table to retrieve its metadata and how to delete a table. It includes waiting for specific table statuses like active or not existing. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("MyTable") // Describe table desc, err := table.Describe().Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Table: %s", desc.Name) log.Printf("Status: %s", desc.Status) log.Printf("Item Count: %d", desc.Items) log.Printf("Size (bytes): %d", desc.Size) log.Printf("Hash Key: %s (%s)", desc.HashKey, desc.HashKeyType) if desc.RangeKey != "" { log.Printf("Range Key: %s (%s)", desc.RangeKey, desc.RangeKeyType) } // List global secondary indexes for _, gsi := range desc.GSI { log.Printf("GSI: %s (Hash: %s, Range: %s)", gsi.Name, gsi.HashKey, gsi.RangeKey) } // List local secondary indexes for _, lsi := range desc.LSI { log.Printf("LSI: %s (Range: %s)", lsi.Name, lsi.RangeKey) } // Wait for table to be active err = table.Wait(ctx, dynamo.ActiveStatus) if err != nil { log.Fatal(err) } // Delete table err = table.DeleteTable().Run(ctx) if err != nil { log.Fatal(err) } // Delete table and wait until gone err = table.DeleteTable().Wait(ctx) if err != nil { log.Fatal(err) } // Wait for table to not exist err = table.Wait(ctx, dynamo.NotExistsStatus) if err != nil { log.Fatal(err) } log.Println("Table deleted") } ``` -------------------------------- ### Create DynamoDB Table with Go Source: https://context7.com/guregu/dynamo/llms.txt Use this code to create a DynamoDB table based on a struct definition. It supports various configurations like provisioned throughput, on-demand billing, DynamoDB Streams, index capacity, projections, tags, and server-side encryption. ```go package main import ( "context" "log" "time" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type UserAction struct { UserID string `dynamo:"ID,hash" index:"Seq-ID-index,range"` Timestamp time.Time `dynamo:",range"` Seq int64 `localIndex:"ID-Seq-index,range" index:"Seq-ID-index,hash"` UUID string `index:"UUID-index,hash"` Action string Data map[string]interface{}, } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) // Create table from struct definition err := db.CreateTable("UserActions", UserAction{}). Provision(5, 5). // Read and write capacity units Run(ctx) if err != nil { log.Fatal(err) } // Create table and wait until ready err = db.CreateTable("UserActions", UserAction{}). Provision(10, 10). Wait(ctx) if err != nil { log.Fatal(err) } // Create table with on-demand billing err = db.CreateTable("UserActions", UserAction{}). OnDemand(true). Run(ctx) if err != nil { log.Fatal(err) } // Create table with DynamoDB Streams err = db.CreateTable("UserActions", UserAction{}). OnDemand(true). Stream(dynamo.NewAndOldImagesView). Run(ctx) if err != nil { log.Fatal(err) } // Provision index capacity separately err = db.CreateTable("UserActions", UserAction{}). Provision(10, 10). ProvisionIndex("UUID-index", 5, 5). ProvisionIndex("Seq-ID-index", 5, 5). Run(ctx) if err != nil { log.Fatal(err) } // Set index projection (what attributes are copied to index) err = db.CreateTable("UserActions", UserAction{}). OnDemand(true). Project("UUID-index", dynamo.KeysOnlyProjection). Project("Seq-ID-index", dynamo.IncludeProjection, "Action", "Data"). Run(ctx) if err != nil { log.Fatal(err) } // Add tags err = db.CreateTable("UserActions", UserAction{}). OnDemand(true). Tag("Environment", "production"). Tag("Team", "backend"). Run(ctx) if err != nil { log.Fatal(err) } // Server-side encryption with KMS err = db.CreateTable("UserActions", UserAction{}). OnDemand(true). SSEEncryption(true, "alias/my-key", dynamo.KMSKeyType). Run(ctx) if err != nil { log.Fatal(err) } log.Println("Table created successfully") } ``` -------------------------------- ### Running DynamoDB Integration Tests with Docker Source: https://github.com/guregu/dynamo/blob/master/README.md Set environment variables to run integration tests against DynamoDB Local using Docker. Tables are created automatically. ```bash # Use Docker to run DynamoDB local on port 8880 docker compose -f '.github/docker-compose.yml' up -d # Run the tests with a fresh table # The tables will be created automatically # The '%' in the table name will be replaced the current timestamp DYNAMO_TEST_ENDPOINT='http://localhost:8880' \ DYNAMO_TEST_REGION='local' \ DYNAMO_TEST_TABLE='TestDB-%' \ AWS_ACCESS_KEY_ID='dummy' \ AWS_SECRET_ACCESS_KEY='dummy' \ AWS_REGION='local' \ go test -v -race ./... -cover -coverpkg=./... ``` -------------------------------- ### Perform a Simple Scan on a DynamoDB Table Source: https://context7.com/guregu/dynamo/llms.txt Retrieves all items from a DynamoDB table. Ensure the table and necessary IAM permissions are configured. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash" Name string Count int Status string } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") var widgets []Widget // Simple scan - get all items err := table.Scan().All(ctx, &widgets) if err != nil { log.Fatal(err) } // Scan with filter err = table.Scan(). Filter("'Count' > ? AND 'Status' = ?", 100, "active"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Scan with projection err = table.Scan(). Project("ID", "Name"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Scan with limit err = table.Scan(). Limit(100). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Parallel scan for large tables (4 segments) err = table.Scan().AllParallel(ctx, 4, &widgets) if err != nil { log.Fatal(err) } // Parallel scan with pagination leks, err := table.Scan().AllParallelWithLastEvaluatedKeys(ctx, 4, &widgets) if err != nil { log.Fatal(err) } // Continue parallel scan if leks != nil { var moreWidgets []Widget leks, err = table.Scan().AllParallelStartFrom(ctx, leks, &moreWidgets) if err != nil { log.Fatal(err) } } // Scan secondary index err = table.Scan(). Index("Status-index"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Iterator-based scan iter := table.Scan().Iter() var w Widget for iter.Next(ctx, &w) { log.Printf("Widget: %+v", w) } if err := iter.Err(); err != nil { log.Fatal(err) } // Parallel iterator parallelIter := table.Scan().IterParallel(ctx, 4) for parallelIter.Next(ctx, &w) { log.Printf("Widget: %+v", w) } if err := parallelIter.Err(); err != nil { log.Fatal(err) } // Count all items count, err := table.Scan().Count(ctx) if err != nil { log.Fatal(err) } log.Printf("Total items: %d", count) } ``` -------------------------------- ### Scan with Attribute Name Placeholder Filter Source: https://context7.com/guregu/dynamo/llms.txt Use '$' as a placeholder for attribute names, which is useful for dynamic attributes. The attribute name is provided as the second argument. ```go attrName := "Status" err := table.Scan(). Filter("$ = ?", attrName, "active"). All(ctx, &widgets) ``` -------------------------------- ### Projection Expression with Complex Paths Source: https://context7.com/guregu/dynamo/llms.txt Use 'ProjectExpr' to specify which attributes to retrieve, including nested attributes and array elements. Attribute names are quoted, and placeholders can be used for dynamic attribute names. ```go err := table.Get("ID", 42). ProjectExpr("ID, 'Name', Tags[0], $", "Status"). One(ctx, &widgets) ``` -------------------------------- ### Scan with Value Placeholder Filter Source: https://context7.com/guregu/dynamo/llms.txt Use '?' as a placeholder for values in filter expressions. Reserved words like 'Count' must be enclosed in single quotes. ```go err := table.Scan(). Filter("'Count' >= ?", cutoff). All(ctx, &widgets) ``` -------------------------------- ### Track Consumed Capacity for Put Operation Source: https://context7.com/guregu/dynamo/llms.txt Monitor WCU consumed by a Put operation by using the ConsumedCapacity method. Reset the ConsumedCapacity variable before tracking. ```go // Track capacity for Put cc = dynamo.ConsumedCapacity{} err = table.Put(Widget{ID: 100, Name: "New"}). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Put consumed: %.2f WCU", cc.Total) ``` -------------------------------- ### Track Consumed Capacity for BatchWrite Operation Source: https://context7.com/guregu/dynamo/llms.txt Monitor WCU consumed by a BatchWrite operation using the ConsumedCapacity method. Reset the ConsumedCapacity variable before tracking. ```go // Track capacity for BatchWrite cc = dynamo.ConsumedCapacity{} _, err = table.Batch("ID").Write(). Put(Widget{ID: 1, Name: "A"}, Widget{ID: 2, Name: "B"}). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Batch write consumed: %.2f WCU", cc.Total) ``` -------------------------------- ### Prepend to a List Attribute in Go Source: https://context7.com/guregu/dynamo/llms.txt Prepends a new element ('first-entry') to the beginning of a list attribute named 'History'. ```go err = table.Update("ID", 42). Prepend("History", "first-entry"). Run(ctx) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Detailed Capacity Breakdown Source: https://context7.com/guregu/dynamo/llms.txt Access detailed capacity information for tables, Global Secondary Indexes (GSIs), and Local Secondary Indexes (LSIs) from the ConsumedCapacity struct. ```go // Detailed capacity breakdown log.Printf("Table capacity: %.2f", cc.Table) for name, cap := range cc.GSI { log.Printf("GSI %s capacity: %.2f", name, cap) } for name, cap := range cc.LSI { log.Printf("LSI %s capacity: %.2f", name, cap) } ``` -------------------------------- ### Scan with Combined Filter Conditions Source: https://context7.com/guregu/dynamo/llms.txt Combine multiple filter conditions using 'AND'. Placeholders are used for both values and attribute names. ```go err := table.Scan(). Filter("'Count' > ? AND 'Status' = ?", cutoff, "active"). All(ctx, &widgets) ``` -------------------------------- ### Scan DynamoDB Table Source: https://github.com/guregu/dynamo/blob/master/README.md Retrieves all items from a DynamoDB table. Ensure the table is not excessively large to avoid performance issues. ```go // get all items var results []widget err = table.Scan().All(ctx, &results) ``` -------------------------------- ### Track Consumed Capacity for Update Operation Source: https://context7.com/guregu/dynamo/llms.txt Use the ConsumedCapacity method to track WCU consumed by an Update operation. Ensure the ConsumedCapacity variable is reset before use. ```go // Track capacity for Update cc = dynamo.ConsumedCapacity{} err = table.Update("ID", 100). Set("Name", "Updated"). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Update consumed: %.2f WCU", cc.Total) ``` -------------------------------- ### Put Item to DynamoDB Table Source: https://context7.com/guregu/dynamo/llms.txt Creates or replaces an item in a DynamoDB table. Supports conditional writes, returning old values, and using CurrentValue for conditional failures. ```go package main import ( "context" "log" "time" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash"` Timestamp time.Time `dynamo:",range"` Name string Count int } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") widget := Widget{ ID: 42, Timestamp: time.Now(), Name: "Gizmo", Count: 100, } // Simple put err := table.Put(widget).Run(ctx) if err != nil { log.Fatal(err) } // Put with condition (only if item doesn't exist) err = table.Put(widget).If("attribute_not_exists(ID)").Run(ctx) if err != nil { if dynamo.IsCondCheckFailed(err) { log.Println("Item already exists") } else { log.Fatal(err) } } // Put and get old value var oldWidget Widget err = table.Put(widget).OldValue(ctx, &oldWidget) if err != nil && err != dynamo.ErrNotFound { log.Fatal(err) } log.Printf("Previous value: %+v", oldWidget) // Put with CurrentValue - gets current item if condition fails wrote, err := table.Put(widget). If("'Count' < ?", 50). CurrentValue(ctx, &oldWidget) if err != nil { log.Fatal(err) } if !wrote { log.Printf("Condition failed, current value: %+v", oldWidget) } } ``` -------------------------------- ### Scan with Multiple Filter Calls (ANDed) Source: https://context7.com/guregu/dynamo/llms.txt Multiple Filter calls are automatically ANDed together. This allows for building complex filter criteria step by step. ```go err := table.Scan(). Filter("'Count' > ?", cutoff). Filter("'Status' = ?", "active"). Filter("'Date' >= ?", lastUpdate). All(ctx, &widgets) ``` -------------------------------- ### Custom Update Expression in Go Source: https://context7.com/guregu/dynamo/llms.txt Performs an update using a custom expression, in this case, incrementing 'Count' by 10. The '?' is a placeholder for the value provided. ```go err = table.Update("ID", 42). SetExpr("'Count' = 'Count' + ?", 10). Run(ctx) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Track Consumed Capacity for Transactions Source: https://context7.com/guregu/dynamo/llms.txt Track WCU consumed by a transaction using the ConsumedCapacity method. The cc.Read and cc.Write fields provide a breakdown of read and write capacity used. ```go // Track capacity for transactions cc = dynamo.ConsumedCapacity{} err = db.WriteTx(). Put(table.Put(Widget{ID: 200, Name: "Tx1"})). Put(table.Put(Widget{ID: 201, Name: "Tx2"})). ConsumedCapacity(&cc). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Transaction consumed: %.2f WCU (Read: %.2f, Write: %.2f)", cc.Total, cc.Read, cc.Write) ``` -------------------------------- ### Conditional Put with Expression Source: https://context7.com/guregu/dynamo/llms.txt Perform a conditional put operation using 'If' to ensure the item does not already exist based on the 'attribute_not_exists' condition. ```go item := Widget{ID: 100, Name: "New Widget", Status: "active"} err := table.Put(item). If("attribute_not_exists(ID)"). Run(ctx) ``` -------------------------------- ### Define DynamoDB Struct with Tags Source: https://github.com/guregu/dynamo/blob/master/README.md Define Go structs for DynamoDB items using struct tags for attribute mapping, including options like changing names, omitting zero values, and ignoring fields. ```go type widget struct { UserID int // Hash key, a.k.a. partition key Time time.Time // Range key, a.k.a. sort key Msg string `dynamo:"Message"` // Change name in the database Count int `dynamo:",omitempty"` // Omits if zero value Children []widget // List of maps Friends []string `dynamo:",set"` // Sets Set map[string]struct{} `dynamo:",set"` // Map sets, too! SecretKey string `dynamo:"-"` // Ignored } ``` -------------------------------- ### Query DynamoDB Items by Primary Key Source: https://context7.com/guregu/dynamo/llms.txt Queries items using the primary key and optional range key conditions. Supports filtering, ordering, pagination, and secondary indexes. Ensure the Widget struct and table are correctly defined. ```go package main import ( "context" "log" "time" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash" Timestamp time.Time `dynamo:",range" Name string Count int Status string } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") var widgets []Widget // Query by hash key, get all items err := table.Get("ID", 42).All(ctx, &widgets) if err != nil { log.Fatal(err) } // Query with range key condition startTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) endTime := time.Date(2024, 12, 31, 23, 59, 59, 0, time.UTC) err = table.Get("ID", 42). Range("Timestamp", dynamo.Between, startTime, endTime). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Range key operators: Equal, NotEqual, Less, LessOrEqual, // Greater, GreaterOrEqual, BeginsWith, Between err = table.Get("ID", 42). Range("Timestamp", dynamo.GreaterOrEqual, startTime). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Filter results (applied after query) err = table.Get("ID", 42). Filter("'Count' > ? AND 'Status' = ?", 10, "active"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Order results (descending) err = table.Get("ID", 42). Order(dynamo.Descending). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Limit results err = table.Get("ID", 42). Limit(10). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Query using secondary index err = table.Get("Status", "active"). Index("Status-index"). All(ctx, &widgets) if err != nil { log.Fatal(err) } // Pagination with LastEvaluatedKey lek, err := table.Get("ID", 42). Limit(10). AllWithLastEvaluatedKey(ctx, &widgets) if err != nil { log.Fatal(err) } // Continue from where we left off if lek != nil { var moreWidgets []Widget err = table.Get("ID", 42). StartFrom(lek). Limit(10). All(ctx, &moreWidgets) if err != nil { log.Fatal(err) } } // Count results count, err := table.Get("ID", 42).Count(ctx) if err != nil { log.Fatal(err) } log.Printf("Count: %d", count) // Using iterator for memory-efficient processing iter := table.Get("ID", 42).Iter() var w Widget for iter.Next(ctx, &w) { log.Printf("Widget: %+v", w) } if err := iter.Err(); err != nil { log.Fatal(err) } log.Printf("Found %d widgets", len(widgets)) } ``` -------------------------------- ### DynamoDB Expression with Attribute Placeholders Source: https://github.com/guregu/dynamo/blob/master/README.md Uses dollar signs ($) as placeholders for attribute names in a delete operation, combined with a condition that checks a value and uses a function like begins_with. ```go table.Delete("ID", 42).If("Score <= ? AND begins_with($, ?)", cutoff, "Name", "G").Run(ctx) ``` -------------------------------- ### Batch Write Items to DynamoDB Source: https://context7.com/guregu/dynamo/llms.txt Writes multiple items to one or more tables in a single request. Supports both put and delete operations. Ensure the table and item structures are correctly defined. ```go package main import ( "context" "log" "github.com/aws/aws-sdk-go-v2/config" "github.com/guregu/dynamo/v2" ) type Widget struct { ID int `dynamo:"ID,hash" Name string } func main() { ctx := context.Background() cfg, _ := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) db := dynamo.New(cfg) table := db.Table("Widgets") // Batch put items widgets := []Widget{ {ID: 1, Name: "Widget A"}, {ID: 2, Name: "Widget B"}, {ID: 3, Name: "Widget C"}, } wrote, err := table.Batch("ID").Write(). Put(widgets[0], widgets[1], widgets[2]). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Wrote %d items", wrote) // Batch delete items wrote, err = table.Batch("ID").Write(). Delete(dynamo.Keys{1}, dynamo.Keys{2}). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Deleted %d items", wrote) // Combined put and delete wrote, err = table.Batch("ID").Write(). Put(Widget{ID: 100, Name: "New Widget"}). Delete(dynamo.Keys{3}). Run(ctx) if err != nil { log.Fatal(err) } // Batch write to multiple tables otherTable := db.Table("OtherWidgets") batch1 := table.Batch("ID").Write().Put(widgets[0]) batch2 := otherTable.Batch("ID").Write().Put(widgets[1]) wrote, err = batch1.Merge(batch2).Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Wrote %d items across tables", wrote) // Batch delete with hash and range key type Event struct { UserID int `dynamo:"UserID,hash" Date string `dynamo:",range" } eventsTable := db.Table("Events") wrote, err = eventsTable.Batch("UserID", "Date").Write(). Delete( dynamo.Keys{1, "2024-01-15"}, dynamo.Keys{1, "2024-01-16"}, ). Run(ctx) if err != nil { log.Fatal(err) } log.Printf("Deleted %d events", wrote) } ```