fsprojects / FSharp.AWS.DynamoDB

F# wrapper API for AWS DynamoDB
MIT License
58 stars 18 forks source link

defaultArg/if_not_exists for the same attribute #74

Closed matti-avilabs closed 2 months ago

matti-avilabs commented 5 months ago

I'm trying to figure out if there's any way to achieve the same end result as is given in the Preventing overwrites of an existing attrubute section from here:

aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW

So far I haven't been successful in any of my attempts so wondering if there's something I'm missing? From digging around it seems if defaultArg would be the way to go but as far as I can tell the only way to construct a valid update expression using that is if the attribute being set and the one passed into defaultArg are not the same ones.

I've tried the following but the resulting expressions are invalid in both cases:

For optional attributes: SET p.Price (defaultArg p.Price price |> Some) For non-optional attributes: SET p.Price (defaultArg (Some p.Price) price)

matti-avilabs commented 2 months ago

Some findings from debugging a little bit:

For a successful case like from here the String attribute ends up being a part of the bindings Map via this codepath.

For the case mentioned in the issue where the attribute being set is the same one being used in the defaultArg call we end up here and as a result the attribute isn't included in the bindings Map and we end up evaluating this.

Any ideas? @samritchie @bartelink

samritchie commented 2 months ago

I think the issue might be the update expression is Some (defaultArg (attribute) (param)) and doesn’t match the specific handling of defaultArg (attribute) (param). Unsure how to match on that, this is all in Eirik’s original code.

Don’t know whether we should support defaultArg on non-optionals - I understand why you’d want it but the expression comes across a bit nonsensical.

matti-avilabs commented 2 months ago

Thanks for looking into this, will be a very useful addition for us. And only being supported for optional fields is fine by me. I'm guessing that using the UpdateOperators syntax directly ends up as the same "stuff" as when using the standard record updates but it does look a bit more natural in that scenario SET p.Price if NOT_EXISTS p.Price then 100 else p.Price