DynamoDB expression attribute name에서 . 문자는 경로 내의 구분자(중첩 속성)로 사용되는 특수 문자이다.
위 문서에서 중첩 속성(Nested Attributes) 섹션의 예제를 AWS SDK Go v2의 DynamoDB expression 패키지를 이용해 아래와 같이 작성해 보았다.
key := expression.Key("Id").Equal(expression.Value(123))
proj := expression.NamesList(expression.Name("ProductReviews.OneStar"))
expr, err := expression.NewBuilder().WithKeyCondition(key).WithProjection(proj).Build()
if err != nil {
return err
}
여기서 expr의 KeyCond, Projection, Names를 출력해보면
fmt.Println(*expr.KeyCondition) // #0 = :0
fmt.Println(*expr.Projection()) // #1.#2
fmt.Println(expr.Names()) // map[#0:Id #1:ProductReviews #2:OneStar]
자동으로 문서에서 제시한 접근법과 동일한 형식으로 표현식이 생성된 것을 볼 수 있다.
만약 ProductReviews.OneStar가 중첩 속성이 아니라 일반 속성이고, 의도적으로 .을 포함해 이름을 정한 경우라면 어떻게 해야 할까?
expression.Name 의 구현을 들여다보면 인수로 받은 문자열을 무조건 .을 기준으로 split하는 것을 볼 수 있다.
대신 이번 경우처럼 속성 이름 내에 .을 유지해야 한다면 expression.NameNoDotSplit 을 사용해야 한다!
proj := expression.NamesList(expression.NameNoDotSplit("ProductReviews.OneStar"))
fmt.Println(*expr.Projection()) // #1
fmt.Println(expr.Names()) // map[#0:Id #1:ProductReviews.OneStar]
그렇다면 이제 문서의 구조가 아래와 같다고 할 때,
{
"Id": "123",
"Attributes": {
"ProductReviews.OneStar": ["review_id"]
}
}
ProductReviews.OneStar 속성에 접근하려면 어떻게 해야 할까?
Attributes.ProductReviews.OneStar 경로를 Attributes와 ProductReviews.OneStar로 나누어서 expression을 만들어야 하는데, 위에 소개한 방법만으로는 접근이 되질 않는다.
expression.Name을 사용한 경우:
proj := expression.NamesList(expression.Name("Attributes.ProductReviews.OneStar"))
fmt.Println(*expr.Projection()) // #1.#2.#3
fmt.Println(expr.Names()) // map[#0:Id #1:Attributes #2:ProductReviews #3:OneStar]
expression.NameNoDotSplit을 사용한 경우:
proj := expression.NamesList(expression.NameNoDotSplit("Attributes.ProductReviews.OneStar"))
fmt.Println(*expr.Projection()) // #1
fmt.Println(expr.Names()) // map[#0:Id #1:Attributes.ProductReviews.OneStar]
이런 경우에는 (expression.NameBuilder).AppendName을 사용해 위의 두 방법들을 조합할 수 있다!
proj := expression.NamesList(expression.Name("Attributes").AppendName(expression.NameNoDotSplit("ProductReviews.OneStar")))
fmt.Println(*expr.Projection()) // #1.#2
fmt.Println(expr.Names()) // map[#0:Id #1:Attributes #2:ProductReviews.OneStar]
. 문자 외의 다른 특수 문자에도 사용이 가능할 것이다.
expression.NameNoDotSplit과 expression.AppendName의 이용법이 잘 설명된 곳을 찾을 수 없어서 짧게 정리해 보았다.
https://github.com/aws/aws-sdk-go/issues/2570
https://github.com/aws/aws-sdk-go-v2/pull/1590
github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.6.12