$ and parse functions
The $
and parse
functions are the primary way to create a ProjectionExpression
in the Low Level API.
They take a string representation of the attribute path that uses the
standard AWS DynamoDB path expression syntax
and return a ProjectionExpression
.
eg
final case class Person(email: String, hobbies: Map[String, List[String]])
val errorOrProjectionExpression: Either[String, ProjectionExpression] = ProjectionExpression.parse("hobbies.sport[0]")
val projectionExpression: ProjectionExpression = ProjectionExpression.$("hobbies.sport[0]")
The parse
function takes a string representation of the path expression (that uses standard AWS DynamoDB path expression syntax).
It returns an Either
which is a Left[String]
when the string projection expression is invalid, or a Right[ProjectionExpression]
when the string projection expression valid and successfully parsed.
The $
function is the unsafe version of the parse
function - if the string projection expression is invalid it throws an IllegalStateException
.
The below table shows the supported path expression syntax:
Expression Syntax | Description |
---|---|
"foo" | top level element |
"foos[0]" | simple top level list element - indexes are zero based |
"foo.bar" | addressing a map element inside a top level element |
"foo_bar" | underscores are valid |
"foo-bar" | hyphens are valid |
`foo.bar ` | special characters such as "dot" need to be escaped with backticks. Here we have an attribute name that contains a special character. |
After the expression is parsed into a ProjectionExpression
, at execution time the AWS API Expression Attributes Names and
Expression Attributes Values
maps are used to escape all path elements safely when required.
Low level representation of ProjectionExpression
​
For those who are interested the below code snippet shows the slightly simplified version of the ProjectionExpression
implementation:
sealed trait ProjectionExpression
object ProjectionExpression {
final case object Root extends ProjectionExpression
final case class ListElement(parent: ProjectionExpression, index: Int) extends ProjectionExpression
final case class MapElement(parent: ProjectionExpression, key: String) extends ProjectionExpression
}
val projectionExpression: ProjectionExpression = ProjectionExpression.$("hobbies.sport[0]")
println(projectionExpression) // ListElement(MapElement(MapElement(Root, "hobbies"), "sport"), 0)
Note that top level elements are represented as MapElement(Root, <ELEMENT_NAME>)
.