Skip to content
expressive DynamoDB library for Go
Go
Branch: master
Clone or download

Latest commit

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci add circleci config May 9, 2020
internal/exprs go lint fixes Dec 10, 2015
.gitignore added gitignore Aug 3, 2015
LICENSE update license Nov 22, 2015
README.md remove extra space in md Mar 21, 2020
batch_test.go support measuring ConsumedCapacity Feb 4, 2018
batchget.go BatchGet: break early given nil Keyed Mar 21, 2020
batchwrite.go support measuring ConsumedCapacity Feb 4, 2018
bench_test.go add go modules support Jan 8, 2019
conditioncheck.go combine multiple If calls with AND Feb 26, 2019
createtable.go fix CreateTable.Index's KeyType (fixes #121) Mar 21, 2020
createtable_test.go add unixtime struct tag support to CreateTable Nov 30, 2019
db.go paging stuff: add LastEvaluatedKey, StartFrom Feb 4, 2018
db_test.go add DB.ListTables Aug 20, 2017
decode.go optimize ItemMarshaler check May 25, 2020
decode_test.go improve handling of NULL-type values Mar 16, 2018
delete.go operations should always report their first error Jan 3, 2020
delete_test.go combine multiple If calls with AND Feb 26, 2019
describetable.go support on-demand billing mode in CreateTable and UpdateTable Feb 26, 2019
describetable_test.go
encode.go add shortcut for raw AV map marshaling May 25, 2020
encode_test.go remove temp test dep Aug 19, 2017
encoding_aws.go compatibility with the official dynamodbattribute package Jun 8, 2017
encoding_aws_test.go add special case for AWSEncoding items May 9, 2020
encoding_test.go optimize ItemMarshaler check May 25, 2020
go.mod update aws-sdk-go version May 9, 2020
go.sum update aws-sdk-go version May 9, 2020
keys.go explicitly specify types of constants (improve godoc) Nov 30, 2019
put.go operations should always report their first error Jan 3, 2020
put_test.go add special case for AWSEncoding items May 9, 2020
query.go use Query for Get when limit is provided Apr 6, 2020
query_test.go support measuring ConsumedCapacity Feb 4, 2018
reserved.go reserved words Mar 3, 2015
retry.go add a blurb about how RetryTimeout is only for non-ctx methods Jun 7, 2017
scan.go Scan: support Count Apr 7, 2020
scan_test.go Scan: support Count Apr 7, 2020
substitute.go combine multiple If calls with AND Feb 26, 2019
substitute_test.go update Update, misc clean up Dec 4, 2015
table.go add more Read and Write info to ConsumedCapacity Jan 14, 2020
table_test.go add more Read and Write info to ConsumedCapacity Jan 14, 2020
ttl.go add UpdateTTL and DescribeTTL Nov 30, 2019
ttl_test.go add UpdateTTL and DescribeTTL Nov 30, 2019
tx.go simplify IdempotentWithToken + docs Nov 30, 2019
tx_test.go update IdempotentWithToken test Nov 30, 2019
update.go operations should always report their first error Jan 3, 2020
update_test.go change Update.Set to remove nil items Jul 15, 2019
updatetable.go support on-demand billing mode in CreateTable and UpdateTable Feb 26, 2019
updatetable_test.go add go modules support Jan 8, 2019

README.md

dynamo GoDoc

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.

Example

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)
}

Expressions

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()

Encoding support

dynamo automatically handles the following interfaces:

This allows you to define custom encodings and provides built-in support for types such as time.Time.

Compatibility with the official AWS library

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))

Integration tests

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

License

BSD

You can’t perform that action at this time.