func(repo *BaseRepository) get(req, res domain.Domain, consistent bool) error { key, err := repo.KeyAttributes(req) if err != nil { return errors.Wrap(err, "failed to get DynamoDB key attributes") } input := &dynamodb.GetItemInput{ TableName: repo.Table(), Key: key, ConsistentRead: aws.Bool(consistent), } // Execute. output, err := repo.DB.GetItem(input) if err != nil { return errors.Wrapf(err, "failed to execute DynamoDB Get API to %s", *repo.Table()) } iflen(output.Item) == 0 { return exception.NewNotFoundError("") } if err = dynamodbattribute.UnmarshalMap(output.Item, &res); err != nil { return errors.Wrap(err, "failed to DynamoDB unmarshal") } returnnil }
// KeyAttributes returns a map of *dymanodb.AttributeValue that is dynamodb table key from the passed struct. func(repo *BaseRepository) KeyAttributes(domain interface{}) (map[string]*dynamodb.AttributeValue, error) { return repo.attributes(domain, func(tag reflect.StructTag)bool { _, ok := tag.Lookup("dynamodbkey") return ok }) }
func(repo *BaseRepository) attributes(domain interface{}, condition func(tag reflect.StructTag)bool) (map[string]*dynamodb.AttributeValue, error) { rv := reflect.Indirect(reflect.ValueOf(domain)) if rv.Kind() != reflect.Struct { returnnil, errors.New("domain must be a struct") } // Create dynamodb attributes. attr, err := dynamodbattribute.MarshalMap(rv.Interface()) if err != nil { returnnil, err } // Delete attributes by condition. var deleteAttr func(rv reflect.Value) deleteAttr = func(rv reflect.Value) { for i, rt := 0, rv.Type(); i < rv.NumField(); i++ { if rv.Field(i).Kind() == reflect.Struct && rt.Field(i).Anonymous { deleteAttr(rv.Field(i)) continue } name, tag := rt.Field(i).Name, rt.Field(i).Tag if !condition(tag) { if dynamodbav := tag.Get("dynamodbav"); dynamodbav != "" { delete(attr, strings.Split(dynamodbav, ",")[0]) } else { delete(attr, name) } } } } deleteAttr(rv) return attr, nil }