# Python
Sort order
Hey,
Alex DeBrie
, thanks for the book. It was much needed.
On page 118, you shared an example of how to add values to a set using the ADD action in an Update Expression, but when I try it in Python, AWS gives me a ValidationException.
On page 118, you shared an example of how to add values to a set using the ADD action in an Update Expression, but when I try it in Python, AWS gives me a ValidationException.
Invalid UpdateExpression: Incorrect operand type for operator or function; operator: ADD, operand type: MAP, typeSet: ALLOWED_FOR_ADD_OPERAND
I googled the error, and found many cases where others have had similar issues with adding to sets, and got around the issue by using the DocumentClient. Is there a similar solution for Python?
Hey
Paul Tihansky
! Can you paste your UpdateItem code here?
From the error message, it looks like you're trying to ADD to a Map rather than a Set.
From the error message, it looks like you're trying to ADD to a Map rather than a Set.
Perhaps it's the way that I'm creating the item.
table.put_item( Item={ 'PK':'Admins#ConsumerX', 'Admins':{'SS':['Alex']} } )
Here's how I am trying to update the item.
table.update_item( Key={ 'PK':'Admins#ConsumerX' }, UpdateExpression="ADD #admins :user", ExpressionAttributeNames={ '#admins':'Admins' }, ExpressionAttributeValues={ ':user':{'SS':['Paul']} } )

I know Alex isn’t a fan of ORM but I’ve been using it for a while now and I really like the clean syntax and what feels like easier code to follow.
https://pynamodb.readthedocs.io/en/latest/
https://pynamodb.readthedocs.io/en/latest/

Are code examples from the book available in Python?
Hey
Harpreet Chatha
! Glad you're liking it, and thanks for the support :)
I don't have the examples in Python at the moment, but I'd really like to. I'm going to try to get them together before re:Invent :).
I don't have the examples in Python at the moment, but I'd really like to. I'm going to try to get them together before re:Invent :).

Hello all!
Alex DeBrie
thanks for the fantastic book. I've leveled up quite a bit in DynamoDB and NoSQL data modeling thanks to your work.
I'm implementing a basic RBAC model more or less straight from the book where the table has a SS attribute called 'admin_role' and I use an update operation to ADD user identifiers to the set to reflect the grant.
When I initialize the organization object in python I default the 'admin_role' object to an empty string set with `admin_role = set([""])`.
Then, when I add the first user to the role, I end up with an empty string plus the new userid I added. So it's something like `["", "userid"]`. I don't want an empty string in there because I have a ConditionExpression of `ConditionExpression=Attr('admin_role').contains(requester)`. I can check for the presence of an empty item in the string set and delete it if length of the string set is > 1 but this seems a bit hacky.
Is there standard pattern for dealing with this situation? Is there a recommended way to model RBAC in DynamoDB specifically for a SaaS app?
I'm implementing a basic RBAC model more or less straight from the book where the table has a SS attribute called 'admin_role' and I use an update operation to ADD user identifiers to the set to reflect the grant.
When I initialize the organization object in python I default the 'admin_role' object to an empty string set with `admin_role = set([""])`.
Then, when I add the first user to the role, I end up with an empty string plus the new userid I added. So it's something like `["", "userid"]`. I don't want an empty string in there because I have a ConditionExpression of `ConditionExpression=Attr('admin_role').contains(requester)`. I can check for the presence of an empty item in the string set and delete it if length of the string set is > 1 but this seems a bit hacky.
Is there standard pattern for dealing with this situation? Is there a recommended way to model RBAC in DynamoDB specifically for a SaaS app?
Hey
Jared Trog
! Glad you're enjoying the book :)
I used to have the same problem, and it drove me crazy. I can't find the code example I want but I think you can do the following:
1) Don't initialize with a set with an empty string. When you add your first element to the set, you can use if_not_exists(#set, :set) to initialize the attribute.
2) When checking for existence, you can do an OR check to first check that the set exists and then check if it contains the requester.
I'm not 100% sure that step (1) will work so will need to try it. If it doesn't work, you'll just need to initialize like you're doing and leave the empty string in there. I don't think the empty string should change the logic?
I used to have the same problem, and it drove me crazy. I can't find the code example I want but I think you can do the following:
1) Don't initialize with a set with an empty string. When you add your first element to the set, you can use if_not_exists(#set, :set) to initialize the attribute.
2) When checking for existence, you can do an OR check to first check that the set exists and then check if it contains the requester.
I'm not 100% sure that step (1) will work so will need to try it. If it doesn't work, you'll just need to initialize like you're doing and leave the empty string in there. I don't think the empty string should change the logic?
