henhal / dynamodb-expressions

Helpers for creating DynamoDB expressions
MIT License
0 stars 0 forks source link

Set new_val = old_val + 1 #3

Closed MrNghia123 closed 7 months ago

MrNghia123 commented 7 months ago

Sorry If I missed something. I could not find how to do this

Set new_val = old_val + 1

MrNghia123 commented 7 months ago

I meant set an attribute from another attribute SET attribute2 = attribute1

henhal commented 7 months ago

Hi @MrNghia123!

Sorry for not having ideal documentation.

Your first example for new_val = old_val + 1 works like this:

{
  new_val: UpdateAction.set(SetValue.add('old_val', 1))
}

However, looking at my code I can interestingly not find any way to simply copy a value from one attribute to another. That's indeed something that should be added.

However, perhaps the most common case for this would be to use SetValue.ifNotExists, since it does copy another attribute but also assigns a default value if that attribute does not exist. Could that work as a workaround?

{
  attribute2: UpdateAction.set(SetValue.ifNotExists('attribute1', 0)
}

Maybe I even deliberately left out the simple copy operator since it fails if the source attribute does not exist, so wrapping such a copy in a if_not_exists is a good idea.

henhal commented 7 months ago

Hi again @MrNghia123!

My apologies, I realized the answer to your question was much easier, you simply prefix a referred attribute with #:

{
  attribute2: '#attribute1'
}

This is somewhat described under "pitfalls" in the README: https://github.com/henhal/dynamodb-expressions/?tab=readme-ov-file#namevalue-ambiguities

To make the syntax easier, by default plain string values are assumed to be string literal values, but you can always explicitly tell the expression builder that the following is instead an attribute name by prepending the string with #. The same goes for : which is used to explicitly signal that the following string is a value, not an attribute name (which is needed if the string value itself starts with # or :). Effectively these character sequences function like "escape characters".

Examples:

Assign attribute2 the value of other attribute1

{
  attribute2: '#attribute1' // SET attribute2 = #attribute1
}

Assign attribute the literal value "value" (normal case):

{
  attribute2: 'value' // SET attribute2 = :value
}

OR, using explicit value prefix:

{
  attribute2: ':value' // SET attribute2 = :value // : is removed from the value
}

Assign attribute the literal value ":value" (the value itself starts with a : character!):

{
  attribute2: '::value' // SET attribute2 = :value, the first colon means "the following is a value"
}

Assign attribute the literal value "#value" (the value itself starts with a # character!):

{
  attribute2: ':#value' // SET attribute2 = :value, the first colon means the following is a value
}

Thanks

MrNghia123 commented 7 months ago

Hi @henhal . Thank you for really helpful information, and such helpful package! I did figure it out about the # prefix, but your tip to use the if_not_exists to avoid error is awesome.

Best regards,

henhal commented 7 months ago

Thanks! I ended up creating some more unit tests for these special cases - and I actually found a bug also regarding special characters in attribute names, so that's been fixed now.

BTW are you using https://github.com/henhal/dynamodb-model as well or just dynamodb-expressions?

I'm closing this issue. Have a nice day!