Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamodb creating a string set

I have a lot of objects with unique IDs. Every object can have several labels associated to it, like this:

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

I'm not planning to store all objects in DynamoDB, only these sets of labels. So it would make sense to add labels like that:

  1. find a record with (id = needed_id)
  2. if there is one, and it has a set named label_set, add a label to this set
  3. if there is no record with such id, or the existing record doesn't have an attribute named label_set, create a record and an attribute, and initialize the attribute with a set consisting of the label

if I used sets of numbers, I could use just ADD operation of UPDATE command. This command does exactly what I described. However, this does not work with sets of strings:

If no item matches the specified primary key:
ADD— Creates an item with supplied primary key and number (or set of numbers) for the attribute value. Not valid for a string type.

so I have to use a PUT operation with Expected set to {"label_set":{"Exists":false}}, followed (in case it fails) by an ADD operation. These are two operations, and it kinda sucks (since you pay per operation, the costs of this will be 2 times more than they could be).

This limitations seems really weird to me. Why are something what works with numbers sets would not work with string sets? Maybe I'm doing something wrong.

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

like image 210
Valentin Golev Avatar asked Jul 28 '12 14:07

Valentin Golev


People also ask

What is string set DynamoDB?

Sets. DynamoDB supports types that represent sets of number, string, or binary values. All the elements within a set must be of the same type. For example, an attribute of type Number Set can only contain numbers; String Set can only contain strings; and so on.

Does DynamoDB support set?

DynamoDB supports the Java Set , List , and Map collection types. The following table summarizes how these Java types map to the DynamoDB types. BOOL (Boolean type), 0 or 1. S (string type).

Which of the following DynamoDB data types include a string set a binary set and a number set?

Scalar − These types represent a single value, and include number, string, binary, Boolean, and null. Document − These types represent a complex structure possessing nested attributes, and include lists and maps. Set − These types represent multiple scalars, and include string sets, number sets, and binary sets.

What is the difference between List and set data type in DynamoDB?

DynamoDB supports multiple types of Sets where unlike Lists, all the elements within a set must be of the same type and all the elements must be also unique. Another difference between Set and List is that Set does not perserve the sequence of elements.


1 Answers

I use string sets from the Java SDK the way you describe all the time and it works for me. Perhaps it has changed? I basically follow the pattern in this doc:

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

ADD— Only use the add action for numbers or if the target attribute is a set (including string sets). ADD does not work if the target attribute is a single string value or a scalar binary value. The specified value is added to a numeric value (incrementing or decrementing the existing numeric value) or added as an additional value in a string set. If a set of values is specified, the values are added to the existing set. For example if the original set is [1,2] and supplied value is [3], then after the add operation the set is [1,2,3], not [4,5]. An error occurs if an Add action is specified for a set attribute and the attribute type specified 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 item.

When your set is empty, it means the attribute isn't present. You can still ADD to it. In fact, a pattern that I've found useful is to simply ADD without even checking for the item. If it doesn't exist, it will create a new item using the specified key and create the attribute set with the value(s) I am adding. If the item exists but the attribute doesn't, it creates the attribute set and adds the value(s). If they both exist, it just adds the value(s).

The only piece that caught me up at first was that the value I had to add was a SS (String set) even if it was only one string value. From DynamoDB's perspective, you are always merging sets, even if the existing set is an empty set (missing) or the new set only contains one value.

IMO, from the way you've described your intent, you would be better off not specifying an existing condition at all. You are having to do two steps because you are enforcing two different situations but you are trying to perform the same action in both. So might as well just blindly add the label and let DynamoDB handle the rest.

like image 97
mckamey Avatar answered Sep 28 '22 06:09

mckamey