Expression builder for dynamo DB.
go get github.com/gauxs/dynexpr/pkg/codegen && go install github.com/gauxs/dynexpr/...@latest
Note: Dynexpr uses Go Modules to manage dependencies.
Dynexpr simplifies the creation of DynamoDB expressions by performing code generation on Go structs representing DynamoDB items. It offers convenient methods to generate expressions for DynamoDB, streamlining the process of building complex queries.
Consider a dynamoDB table storing users transaction details. A single DDB item schema looks like:
// dynexpr:generate
type Transaction struct {
UserID *string `json:"user_id,omitempty" dynexpr:"partitionKey"`
TransactionID *string `json:"transaction_id,omitempty" dynexpr:"sortKey"`
Amount *int `json:"amount,omitempty"`
}
Building expressions
// build expression builder
dynexprBldr := test_models.NewTransaction_ExpressionBuilder()
dynexprBldr.Build()
ddbItem := dynexprBldr.DDBItemRoot()
// project attributes
ddbItem.AR().UserID.Project()
ddbItem.AR().TransactionID.Project()
ddbItem.AR().Amount.Project()
// add condition
ddbItem.AR().TransactionID.AndWithCondition()(
ddbItem.AR().TransactionID.GetKeyBuilder().Equal(expression.Value("userID#123")))
// update attributes
ddbItem.AR().Amount.AddValue(dynexprv1.UPDATE_SET, 9000)
// building AWS dynamoDB expression
projBldr, _ := dynexprBldr.BuildProjectionBuilder()
updtBldr, _ := dynexprBldr.BuildUpdateBuilder()
dynamoDBExpr, err := expression.NewBuilder().
WithProjection(*projBldr).
WithKeyCondition(*(dynexprBldr.BuildKeyConditionBuilder())).
WithUpdate(*updtBldr).
Build()
// dynamoDBExpr.Projection(): #1, #0, #2
// dynamoDBExpr.KeyCondition(): #0 = :0
// dynamoDBExpr.Update(): SET #2 = :1
// dynamoDBExpr.Names(): {"#0":"transaction_id","#1":"user_id","#2":"amount"}
// dynamoDBExpr.Values(): {":0":{"B":null,"BOOL":null,"BS":null,"L":null,"M":null,"N":null,"NS":null,
// "NULL":null,"S":"userID#123","SS":null},":1":{"B":null,"BOOL":null,"BS":null,
// "L":null,"M":null,"N":"9000","NS":null,"NULL":null,"S":null,"SS":null}}
Code generated for the above model will be:
// Code generated by dynexpr for building expression. DO NOT EDIT.
type Transaction_ExpressionBuilder struct {
UserID dynexpr.DynamoKeyAttribute[*string]
TransactionID dynexpr.DynamoKeyAttribute[*string]
Amount dynexpr.DynamoAttribute[*int]
}
func (o *Transaction_ExpressionBuilder) BuildTree(name string) *dynexpr.DynamoAttribute[*Transaction_ExpressionBuilder] {
o = &Transaction_ExpressionBuilder{}
o.UserID = *dynexpr.NewDynamoKeyAttribute[*string]().WithName("user_id")
o.TransactionID = *dynexpr.NewDynamoKeyAttribute[*string]().WithName("transaction_id")
o.Amount = *dynexpr.NewDynamoAttribute[*int]().WithName("amount")
return dynexpr.NewDynamoAttribute[*Transaction_ExpressionBuilder]().
WithAccessReference(o).
WithName(name).
WithChildAttribute(&o.UserID).
WithChildAttribute(&o.TransactionID).
WithChildAttribute(&o.Amount)
}
func NewTransaction_ExpressionBuilder() dynexpr.DDBItemExpressionBuilder[*Transaction_ExpressionBuilder] {
return dynexpr.NewDDBItemExpressionBuilder(&Transaction_ExpressionBuilder{})
}
-
dynexpr:generate
: should be declared over the struct which represents a single item of dynamoDB.
// dynexpr:generate
type DDBItem struct {
...
}
-
dynexpr:"partitionKey"
: to declare that the attribute is partion key of the dynamoDB item.
type DDBItem struct {
PK *string `json:"pk,omitempty" dynexpr:"partitionKey"`
...
}
-
dynexpr:"sortKey"
: to declare that the attribute is sort key of the dynamoDB item.
type DDBItem struct {
SK *string `json:"sk,omitempty" dynexpr:"sortKey"`
...
}
If your DynamoDB schema has a limited number of attributes, this solution may be excessive. However, it becomes particularly convenient for cases where the DynamoDB schema includes 30 or more attributes.
The project is licensed under the MIT License.
go run cmd/main.go -output_filename test/expression/data/person_dynexpr.go test/expression/data