Dynamodb creates a rowset

I have many objects with unique identifiers. Each object can have several labels associated with it, for example:

123: ['a', 'hello'] 456: ['dsajdaskldjs'] 789: (no labels associated yet) 

I do not plan to store all objects in DynamoDB, only these label sets. Therefore, it would be advisable to add such shortcuts:

  • find the entry with (id = needed_id)
  • if there is one and it has a set called label_set , add a label to this set
  • if there is no record with this identifier, or if the existing record does not have an attribute named label_set , create a record and attribute and initialize the attribute using a set of labels

If I used sets of numbers, I could only use the ADD command of the UPDATE command. This command does exactly what I described. However, this does not work with row sets:

If the item does not match the specified primary key:
ADD- Creates an element with the provided primary key and number (or set of numbers) for the attribute value. Not valid for string type.

so I have to use the PUT operation with Expected set to {"label_set":{"Exists":false}} , and then (if it fails) using the ADD operation. These are two operations, and this sucks (since you pay for the operation, the cost of this will be 2 times more than they can be).

These restrictions seem very strange to me. Why doesn't something that works with sets of numbers not work with sets of strings? Maybe I'm doing something wrong.

Using many records, such as (123, 'a'), (123, 'hello') instead of a single record per object with a set, is not a solution: I want to get all the values ​​from the set at once, without any scans.

+4
source share
4 answers

I use the rowset from the Java SDK the way you describe all the time, and this works for me. Perhaps this has changed? I basically follow the pattern in this document:

http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/API_UpdateItem.html

ADD - Use only the add action for numbers or if the target attribute is a set (including a set of strings). ADD does not work if the target Attribute is a single-line value or a scalar binary value. the specified value is added to the numerical value (increment or decrement of the existing numerical value) or added as an additional value in the rowset. If a set of values ​​is specified, the values ​​are added to the existing set. For example, if the initial set is [1,2] and the set value is [3], then after the addition operation the set is [1,2,3], but not [4,5]. An error occurred if the Add action is specified for the set attribute and the specified attribute type does not match the existing set type.

If you use ADD for an attribute that does not exist, the attribute and its values ​​are added to the element.

When your set is empty, it means the attribute is missing. You can still ADD to it. In fact, the pattern I found useful is just ADD , without even checking the element. If it does not exist, it will create a new element using the specified key and create an attribute set with the values ​​added by me. If an element exists but the attribute does not, it creates a set of attributes and adds values. If they both exist, they simply add the value (s).

The only thing that caught me was that the value I had to add was SS (String set), even if it was only one string value. From the point of view of DynamoDB, you always merge sets, even if the existing set is empty (missing) or the new set contains only one value.

IMO, by the way you described your intention, you better not indicate the existing state at all. You need to take two steps because you are performing two different situations, but you are trying to perform the same action in both cases. So maybe just blindly add a shortcut and let DynamoDB handle the rest.

+4
source

Perhaps you could: (pseudocode)

 try: add_with_update_item(hash_key=42, "label") except: element = new Element(hash_key=42, labels=["label"]) element.save() 

With this graceful recovery approach, you need 1 call in the general case, 2 otherwise.

0
source

You cannot use sets to do what you want, because Dynamo Db does not support empty sets. I would suggest just using a custom schema string and building a set of it yourself.

0
source

To avoid two operations, you can add "ConditionExpression" to your element. For example, add this field / value to your element:

 "ConditionExpression": "attribute_not_exists(RecordID) and attribute_not_exists(label_set)" 

Source documentation.

Edit: I found a really good guide on how to use conditional statements

0
source

All Articles