Documentation ¶
Index ¶
- Variables
- func AllOf[T any](seq ...interface{ WriterOpt(T) }) interface{ ... }
- func Decode(av types.AttributeValue, val interface{}, coder ...Coder) (err error)
- func Encode(val interface{}, coder ...Coder) (types.AttributeValue, error)
- func OneOf[T any](seq ...interface{ WriterOpt(T) }) interface{ ... }
- type CodecOf
- type Coder
- type ConditionExpression
- func (ce ConditionExpression[T, A]) Between(a, b A) interface{ ... }
- func (ce ConditionExpression[T, A]) Contains(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) Eq(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) Exists() interface{ ... }
- func (ce ConditionExpression[T, A]) Ge(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) Gt(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) HasPrefix(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) In(seq ...A) interface{ ... }
- func (ce ConditionExpression[T, A]) Is(val string) interface{ ... }
- func (ce ConditionExpression[T, A]) Le(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) Lt(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) Ne(val A) interface{ ... }
- func (ce ConditionExpression[T, A]) NotExists() interface{ ... }
- func (ce ConditionExpression[T, A]) Optimistic(val A) interface{ ... }
- type DynamoDB
- type Option
- type Options
- type Storage
- func (db *Storage[T]) BatchGet(ctx context.Context, keys []T, opts ...interface{ GetterOpt(T) }) ([]T, error)
- func (db *Storage[T]) BatchPut(ctx context.Context, entities []T, opts ...interface{ WriterOpt(T) }) ([]T, error)
- func (db *Storage[T]) BatchRemove(ctx context.Context, keys []T, opts ...interface{ WriterOpt(T) }) ([]T, error)
- func (db *Storage[T]) Get(ctx context.Context, key T, opts ...interface{ GetterOpt(T) }) (T, error)
- func (db *Storage[T]) Match(ctx context.Context, key T, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ ... }, error)
- func (db *Storage[T]) MatchKey(ctx context.Context, key dynamo.Thing, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ ... }, error)
- func (db *Storage[T]) Put(ctx context.Context, entity T, opts ...interface{ WriterOpt(T) }) error
- func (db *Storage[T]) Remove(ctx context.Context, key T, opts ...interface{ WriterOpt(T) }) (T, error)
- func (db *Storage[T]) Update(ctx context.Context, entity T, opts ...interface{ WriterOpt(T) }) (T, error)
- func (db *Storage[T]) UpdateWith(ctx context.Context, expression UpdateItemExpression[T], ...) (T, error)
- type UpdateExpression
- func (ue UpdateExpression[T, A]) Add(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Append(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Dec(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Inc(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Minus(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Prepend(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Remove() interface{ ... }
- func (ue UpdateExpression[T, A]) Set(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) SetNotExists(val A) interface{ ... }
- func (ue UpdateExpression[T, A]) Union(val A) interface{ ... }
- type UpdateItemExpression
Constants ¶
This section is empty.
Variables ¶
var ( // Set Global Secondary Index for the session WithGlobalSecondaryIndex = opts.ForName[Options, string]("index") // Configure the custom name for HashKey, default one is "prefix" WithHashKey = opts.ForName[Options, string]("hashKey") // Configure the custom name for SortKey, default one is "suffix" WithSortKey = opts.ForName[Options, string]("sortKey") // Configure CURIE prefixes, does nothing for DynamoDB WithPrefixes = opts.FMap(func(*Options, curie.Prefixes) error { return nil }) // Enables strict serialization of the type, the I/O would fails // if type attributes does not match the storage schema. // It demand that storage schema "knows" all type attributes. WithStrictType = opts.ForName[Options, bool]("useStrictType") // Set DynamoDB client for the client WithService = opts.ForType[Options, DynamoDB]() // Set DynamoDB client for the client WithDynamoDB = opts.ForType[Options, DynamoDB]() // Configure client's DynamoDB to use provided the aws.Config WithConfig = opts.FMap(optsFromConfig) // Use default aws.Config for all DynamoDB clients WithDefaultDDB = opts.From(optsDefaultDDB) )
Functions ¶
func AllOf ¶ added in v3.0.5
func AllOf[T any](seq ...interface{ WriterOpt(T) }) interface{ WriterOpt(T) }
AllOf joins multiple constraint into higher-order constraint that is true when all of defined is true (aka AND logical expression)
func Decode ¶
func Decode(av types.AttributeValue, val interface{}, coder ...Coder) (err error)
Decode is a helper function to decode core domain types from Dynamo DB format. The helper ensures compact URI de-serialization from DynamoDB schema.
type MyType struct { ID MyComplexType Name MyComplexType } var ID, Name = dynamo.Codec2[MyType, MyDynamoType, MyDynamoType]("ID", "Name") func (x *MyType) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { type tStruct *MyType return dynamo.Decode(av, tStruct(x), ID.Decode((*MyDynamoType)(&x.ID)), Name.Decode((*MyDynamoType)(&x.Name)), ) }
func Encode ¶
func Encode(val interface{}, coder ...Coder) (types.AttributeValue, error)
Encode is a helper function to encode core domain types into struct. The helper ensures compact URI serialization into DynamoDB schema.
type MyType struct { ID MyComplexType Name MyComplexType } var ID, Name = dynamo.Codec2[MyType, MyDynamoType, MyDynamoType]("ID", "Name") func (x MyType) MarshalDynamoDBAttributeValue() (types.AttributeValue, error) { type tStruct MyType return dynamo.Encode(av, tStruct(x), ID.Encode(MyDynamoType(x.ID)), Name.Encode(MyDynamoType(x.Name)), ) }
Types ¶
type CodecOf ¶
CodecOf for struct fields, the type implement Encode/Decode primitives. Codec helps to implement semi-automated encoding/decoding algebraic data type into the format compatible with storage.
Let's consider scenario were application uses complex types that skips implementation of marshal/unmarshal protocols. Here the type MyComplexType needs to be casted to MyDynamoType that knows how to marshal/unmarshal the type.
type MyType struct { ID MyComplexType Name MyComplexType } var ( ID = dynamo.Codec[MyType, MyDynamoType]("ID") Name = dynamo.Codec[MyType, MyDynamoType]("Name") ) func (t MyType) MarshalDynamoDBAttributeValue() (*dynamodb.AttributeValue, error) { type tStruct MyType return dynamo.Encode(tStruct(p), ID.Encode(MyDynamoType(t.ID)), Name.Encode(MyDynamoType(t.Name)), ) }
type Coder ¶
type Coder func(map[string]types.AttributeValue) (map[string]types.AttributeValue, error)
Coder is a function, applies transformation of generic dynamodb AttributeValue
type ConditionExpression ¶
type ConditionExpression[T dynamo.Thing, A any] struct { // contains filtered or unexported fields }
func ClauseFor ¶
func ClauseFor[T dynamo.Thing, A any](attr ...string) ConditionExpression[T, A]
See DynamoDB Conditional Expressions
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html
Schema declares type descriptor to express Storage I/O Constrains.
Let's consider a following example:
type Person struct { curie.ID Name string `dynamodbav:"anothername,omitempty"` }
How to define a condition expression on the field Name? Golang struct defines and refers the field by `Name` but DynamoDB stores it under the attribute `anothername`. Struct field dynamodbav tag specifies serialization rules. Golang does not support a typesafe approach to build a correspondence between `Name` ⟷ `anothername`. Developers have to utilize dynamodb attribute name(s) in conditional expression and Golang struct name in rest of the code. It becomes confusing and hard to maintain.
The Schema is helpers to declare builders for conditional expressions. Just declare a global variables next to type definition and use them across the application.
var ( name = dynamo.ClauseFor[Person, string]("Name") addr = dynamo.ClauseFor[Person, Address]() ) name.Eq("Joe Doe") name.NotExists()
func (ConditionExpression[T, A]) Between ¶
func (ce ConditionExpression[T, A]) Between(a, b A) interface{ WriterOpt(T) }
Between attribute condition
name.Between(a, b) ⟼ Field BETWEEN :a AND :b
func (ConditionExpression[T, A]) Contains ¶
func (ce ConditionExpression[T, A]) Contains(val A) interface{ WriterOpt(T) }
Contains attribute condition
name.Contains(x) ⟼ contains(Field, :value)
func (ConditionExpression[T, A]) Eq ¶
func (ce ConditionExpression[T, A]) Eq(val A) interface{ WriterOpt(T) }
Eq is equal condition
name.Eq(x) ⟼ Field = :value
func (ConditionExpression[T, A]) Exists ¶
func (ce ConditionExpression[T, A]) Exists() interface{ WriterOpt(T) }
Exists attribute constrain
name.Exists(x) ⟼ attribute_exists(name)
func (ConditionExpression[T, A]) Ge ¶
func (ce ConditionExpression[T, A]) Ge(val A) interface{ WriterOpt(T) }
Ge is greater or equal constrain
name.Le(x) ⟼ Field >= :value
func (ConditionExpression[T, A]) Gt ¶
func (ce ConditionExpression[T, A]) Gt(val A) interface{ WriterOpt(T) }
Gt is greater than constrain
name.Le(x) ⟼ Field > :value
func (ConditionExpression[T, A]) HasPrefix ¶
func (ce ConditionExpression[T, A]) HasPrefix(val A) interface{ WriterOpt(T) }
HasPrefix attribute condition
name.HasPrefix(x) ⟼ begins_with(Field, :value)
func (ConditionExpression[T, A]) In ¶
func (ce ConditionExpression[T, A]) In(seq ...A) interface{ WriterOpt(T) }
In attribute condition
name.Between(a, b, c) ⟼ Field IN (:a, :b, :c)
func (ConditionExpression[T, A]) Is ¶
func (ce ConditionExpression[T, A]) Is(val string) interface{ WriterOpt(T) }
Is matches either Eq or NotExists if value is not defined
func (ConditionExpression[T, A]) Le ¶
func (ce ConditionExpression[T, A]) Le(val A) interface{ WriterOpt(T) }
Le is less or equal constain
name.Le(x) ⟼ Field <= :value
func (ConditionExpression[T, A]) Lt ¶
func (ce ConditionExpression[T, A]) Lt(val A) interface{ WriterOpt(T) }
Lt is less than constraint
name.Lt(x) ⟼ Field < :value
func (ConditionExpression[T, A]) Ne ¶
func (ce ConditionExpression[T, A]) Ne(val A) interface{ WriterOpt(T) }
Ne is non equal condition
name.Ne(x) ⟼ Field <> :value
func (ConditionExpression[T, A]) NotExists ¶
func (ce ConditionExpression[T, A]) NotExists() interface{ WriterOpt(T) }
NotExists attribute constrain
name.NotExists(x) ⟼ attribute_not_exists(name)
func (ConditionExpression[T, A]) Optimistic ¶ added in v3.0.5
func (ce ConditionExpression[T, A]) Optimistic(val A) interface{ WriterOpt(T) }
Optimistic defines optimistic concurrency control (aka optimistic lock) condition.
name.Optimistic(x) ⟼ (Field = :value) or (attribute_not_exists(name))
type DynamoDB ¶
type DynamoDB interface { GetItem(context.Context, *dynamodb.GetItemInput, ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error) PutItem(context.Context, *dynamodb.PutItemInput, ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error) DeleteItem(context.Context, *dynamodb.DeleteItemInput, ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error) UpdateItem(context.Context, *dynamodb.UpdateItemInput, ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error) Query(context.Context, *dynamodb.QueryInput, ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) BatchGetItem(context.Context, *dynamodb.BatchGetItemInput, ...func(*dynamodb.Options)) (*dynamodb.BatchGetItemOutput, error) BatchWriteItem(ctx context.Context, params *dynamodb.BatchWriteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error) }
DynamoDB declares interface of original AWS DynamoDB API used by the library
type Storage ¶
type Storage[T dynamo.Thing] struct { Options // contains filtered or unexported fields }
Storage type
func (*Storage[T]) BatchPut ¶ added in v3.0.6
func (db *Storage[T]) BatchPut(ctx context.Context, entities []T, opts ...interface{ WriterOpt(T) }) ([]T, error)
Put multiple items at once
func (*Storage[T]) BatchRemove ¶ added in v3.0.6
func (db *Storage[T]) BatchRemove(ctx context.Context, keys []T, opts ...interface{ WriterOpt(T) }) ([]T, error)
Remove multiple items at once
func (*Storage[T]) Match ¶
func (db *Storage[T]) Match(ctx context.Context, key T, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ MatcherOpt(T) }, error)
Match applies a pattern matching to elements in the table
func (*Storage[T]) MatchKey ¶
func (db *Storage[T]) MatchKey(ctx context.Context, key dynamo.Thing, opts ...interface{ MatcherOpt(T) }) ([]T, interface{ MatcherOpt(T) }, error)
Match applies a pattern matching to elements in the table
func (*Storage[T]) Remove ¶
func (db *Storage[T]) Remove(ctx context.Context, key T, opts ...interface{ WriterOpt(T) }) (T, error)
Remove discards the entity from the table
func (*Storage[T]) Update ¶
func (db *Storage[T]) Update(ctx context.Context, entity T, opts ...interface{ WriterOpt(T) }) (T, error)
Update applies a partial patch to entity and returns new values
func (*Storage[T]) UpdateWith ¶
func (db *Storage[T]) UpdateWith(ctx context.Context, expression UpdateItemExpression[T], opts ...interface{ WriterOpt(T) }) (T, error)
Update applies a partial patch to entity using update expression abstraction
type UpdateExpression ¶
type UpdateExpression[T dynamo.Thing, A any] struct { // contains filtered or unexported fields }
func UpdateFor ¶
func UpdateFor[T dynamo.Thing, A any](attr ...string) UpdateExpression[T, A]
func (UpdateExpression[T, A]) Add ¶
func (ue UpdateExpression[T, A]) Add(val A) interface{ UpdateExpression(T) }
Add new attribute and increment value
name.Add(x) ⟼ ADD Field :value
func (UpdateExpression[T, A]) Append ¶
func (ue UpdateExpression[T, A]) Append(val A) interface{ UpdateExpression(T) }
Append element to list
name.Inc(x) ⟼ SET Field = list_append (Field, :value)
func (UpdateExpression[T, A]) Dec ¶
func (ue UpdateExpression[T, A]) Dec(val A) interface{ UpdateExpression(T) }
Decrement attribute
name.Inc(x) ⟼ SET Field = Field - :value
func (UpdateExpression[T, A]) Inc ¶
func (ue UpdateExpression[T, A]) Inc(val A) interface{ UpdateExpression(T) }
Increment attribute
name.Inc(x) ⟼ SET Field = Field + :value
func (UpdateExpression[T, A]) Minus ¶
func (ue UpdateExpression[T, A]) Minus(val A) interface{ UpdateExpression(T) }
Delete elements from set
name.Minus(x) ⟼ ADD Field :value
func (UpdateExpression[T, A]) Prepend ¶
func (ue UpdateExpression[T, A]) Prepend(val A) interface{ UpdateExpression(T) }
Prepend element to list
name.Inc(x) ⟼ SET Field = list_append (:value, Field)
func (UpdateExpression[T, A]) Remove ¶
func (ue UpdateExpression[T, A]) Remove() interface{ UpdateExpression(T) }
Remove attribute
name.Remove() ⟼ REMOVE Field
func (UpdateExpression[T, A]) Set ¶
func (ue UpdateExpression[T, A]) Set(val A) interface{ UpdateExpression(T) }
Set attribute
name.Inc(x) ⟼ SET Field = :value
func (UpdateExpression[T, A]) SetNotExists ¶
func (ue UpdateExpression[T, A]) SetNotExists(val A) interface{ UpdateExpression(T) }
Set attribute if not exists
name.Inc(x) ⟼ SET Field = if_not_exists(Field, :value)
func (UpdateExpression[T, A]) Union ¶
func (ue UpdateExpression[T, A]) Union(val A) interface{ UpdateExpression(T) }
Add elements to set
name.Union(x) ⟼ ADD Field :value
type UpdateItemExpression ¶
type UpdateItemExpression[T dynamo.Thing] struct {
// contains filtered or unexported fields
}
func Updater ¶
func Updater[T dynamo.Thing](entity T, opts ...interface{ UpdateExpression(T) }) UpdateItemExpression[T]