import "github.com/guregu/dynamo"
dynamo is an expressive DynamoDB client for Go, with an API heavily inspired by mgo. dynamo integrates with the official AWS SDK.
dynamo is still under development, so the API may change rarely. However, breaking changes will be avoided and the API can be considered relatively stable.
package dynamo
import (
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/guregu/dynamo"
)
// Use struct tags much like the standard JSON library,
// you can embed anonymous structs too!
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"`
Count int `dynamo:",omitempty"`
Friends []string `dynamo:",set"` // Sets
Set map[string]struct{} `dynamo:",set"` // Map sets, too!
SecretKey string `dynamo:"-"` // Ignored
Category string `dynamo:"Category"` // Global Secondary Index
Children []any // Lists
}
func main() {
db := dynamo.New(session.New(), &aws.Config{Region: aws.String("us-west-2")})
table := db.Table("Widgets")
// put item
w := widget{UserID: 613, Time: time.Now(), Msg: "hello"}
err := table.Put(w).Run()
// get the same item
var result widget
err = table.Get("UserID", w.UserID).
Range("Time", dynamo.Equal, w.Time).
Filter("'Count' = ? AND $ = ?", w.Count, "Message", w.Msg). // placeholders in expressions
One(&result)
// get by index
err = table.Get("Category", "hoge").
Index("category-index").
One(&result)
// get all items
var results []widget
err = table.Scan().All(&results)
}
dynamo will help you write expressions used to filter results in queries and scans, and add conditions to puts and deletes.
Attribute names may be written as is if it is not a reserved word, or be escaped with single quotes (''
). You may also use dollar signs ($
) as placeholders for attribute names. DynamoDB has very large amount of reserved words so it may be a good idea to just escape everything.
Question marks (?
) are used as placeholders for attribute values. DynamoDB doesn't have value literals, so you need to substitute everything.
Please see the DynamoDB reference on expressions for more information.
// Using single quotes to escape a reserved word, and a question mark as a value placeholder.
// Finds all items whose date is greater than or equal to lastUpdate.
table.Scan().Filter("'Date' >= ?", lastUpdate).All(&results)
// Using dollar signs as a placeholder for attribute names.
// Deletes the item with an ID of 42 if its score is at or below the cutoff, and its name starts with G.
table.Delete("ID", 42).If("Score <= ? AND begins_with($, ?)", cutoff, "Name", "G").Run()
// Put a new item, only if it doesn't already exist.
table.Put(item{ID: 42}).If("attribute_not_exists(ID)").Run()
dynamo automatically handles the following interfaces:
dynamo.Marshaler
anddynamo.Unmarshaler
dynamodbattribute.Marshaler
anddynamodbattribute.Unmarshaler
encoding.TextMarshaler
andencoding.TextUnmarshaler
This allows you to define custom encodings and provides built-in support for types such as time.Time
.
dynamo has been in development before the official AWS libraries were stable. We use a different encoder and decoder than the dynamodbattribute package. dynamo uses the dynamo
struct tag instead of the dynamodbav
struct tag, and we also prefer to automatically omit invalid values such as empty strings, whereas the dynamodbattribute package substitutes null values for them. Items that satisfy the dynamodbattribute.(Un)marshaler
interfaces are compatibile with both libraries.
In order to use dynamodbattribute's encoding facilities, you must wrap objects passed to dynamo with dynamo.AWSEncoding
. Here is a quick example:
// 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()
// When getting an item you MUST pass a pointer to AWSEncoding!
var someBook book
err := db.Table("Books").Get("ID", 555).One(dynamo.AWSEncoding(&someBook))
By default, tests are run in offline mode. Create a table called TestDB
, with a Number Parition Key called UserID
and a String Sort Key called Time
. Change the table name with the environment variable DYNAMO_TEST_TABLE
. You must specify DYNAMO_TEST_REGION
, setting it to the AWS region where your test table is.
DYNAMO_TEST_REGION=us-west-2 go test github.com/guregu/dynamo/... -cover
BSD