Get data based on sort index AWS dynamoDB - amazon-web-services

I have a DynamoDB table like this:
I want to list all posts irrespective of users, i-e by getting all data whose sort key is "post". How can I achieve this?
I have heard about Global Secondary Index, but couldn't figure out how to use them.

You create a global secondary index with a Key Schema like this:
Partition Key: SK attribute of the base table
Sort Key: PK attribute of the base table
It's called an inverted index. Then you can Query the Global Secondary Index by specifying the IndexName in the Query and search for all items that have "post" as the value for SK.

Related

User ID vs ID for primary key dynamoDB

I have a table in which has a "userId" column (set as a partition key) and a "createdAt" column (set as the sort key) so they form up a composite primary key.
I also need to find the exact row in case I don't have the User ID available, so I made another column "id" and made it as a global secondary index.
In my case, should I make the "id" column the primary key and remove the "userId" as the partition key or will this remove the feature of what "Partitioning" actually does by the DynamoDB?
Similarly, If I need to delete a row from the table, should I send "createdAt" field from the front end to be able to find out the exact row? Does this make sense? Sending the "id" of the row seems more good to me to be able to delete the row.
You probably don't want to put a timestamp in your user primary keys. Why? You'd need to know the exact time the user was created to fetch a user, which is probably not what you want.
Consider using a partition key of USER#<user_id> and a sort key of something predictable, like A or METADATA or USER#<user_id>. This allows you to fetch/delete a user by their ID.
If you have access patterns around fetching users in order of account creation, you can create a GSI with the sort key set to the createdAt attribute.

How to have a composite key in dynamoDB?

I have the following JSON in dynamo:
{
cdItem: "123456",
dtItem: "2021-03-01"
}
My hashkey is cdItem.
I would need my dtItem also be a key. So that if I send an item with the same cdItem, but different dtItem, it creates a new record and does not update the existing one.
How can I do this? Or, is it possible to do this?
There are multiple ways you can implement this and they depend on your access patterns.
If you only want to request an item for which you know both the cdItem as well as the dtItem values you could just overload the partition key by concatenating them, e.g. 123456#2021-03-01 that way you could keep your existing table.
A more flexible solution would be using a composite primary key, which is a combination of a partition and a sort key. This requires you to create a new table.
I'd set it up like this:
cdItem (Partition Key)
dtItem (Sort Key
123456
2021-02-27
123456
2021-02-28
123456
2021-03-01
654321
2021-03-01
You'll have to provide both of those attributes on each PutItem request.
You can also call GetItem with both values to retrieve a single item and you can select all dtItem values for a given cdItem value using the Query API as well as do some filtering on the value of dtItem.

DynamoDB create another table for query a list attribute in a table?

I am inheriting DynamoDB from someone.
There is a table called Item. It used an item id as a partition key which is also primary key(no sort key in this table).
Each item has a Tags attribute which is a list like tag1, tag2, etc. Now, I got a new use case that I want to query item by tags efficiently. What is the best solution to this?
I am thinking creating another table for Tags which will be a partition key and item id becomes its sort key. Is it the best solution besides re-designing Item table?
Partition key(Primary key) tags. name other attributes....
id1 t1,t2. Item1Name ...
id2 t1,t3,t4,t5. Item2Name ...
...
My idea is to create another table, is it the best solution? any idea is appreciated.
Partition key(Primary key) sort key
t1 id1
t1 id2
t2 id1
t3 id2
t4 id2
t5 id2
...
I think the best solution would require you to recreate the table and take the benefit of using a GSI (Global Secondary Index).
If you create the DynamoDB table to have a partition of primary key and then then a sort key of the tag then the data associated with the row you would perform a query like normal to retrieve based on your ID.
You would then create a GSI with the partition key of the tag (and perhaps sort key as the id assuming you need it) along with projecting any attributes you would want available to the GSI.
This approach is better than attempting to manage data between 2 seperate DynamoDB tables as you will only have to make the change once but can retrieve the data easily for both scenarios.

Can you query by a range in a GSI in DynamoDB

Suppose I had a users and images tables in DynamoDB.
users table
userId (hash) name email
images table
imagesId (hash) userId filename
How should I set up the range or GSI if I wanted to get all images for a single userId? Should images table be a composite key with imageId (hash) and userId (range) and search by range (if possible)? or should userId (be a GSI) and query just be userId?
It looks like you could add a GSI on your Images table with the reverse key schema of your table:
hash key - userId
range key - imagesId
filename - additional property
You can then query this GSI with a userId to get all of its associated imagesId.
You cannot query using just a range key in DynamoDB.
Unless you want your query results from the images table to be sorted by userId, there's no point to using it as a range key. If you want to retrieve all of the images with a certain userId from the images table using a query, you need to use a GSI on userId.

Dynamodb scan in sorted order

Hi I have a dynamodb table. I want the service to return me all the items in this table and the order is by sorting on one attribute.
Do I need to create a global secondary index for this? If that is the case, what should be the hash key, what is the range key?
(Note that query on gsi must specify a "EQ" comparator on the hash key of GSI.)
Thanks a lot!
Erben
If you know the HashKey, then any query will return the items sorted by Range key. From the documentation:
Query results are always sorted by the range key. If the data type of the range key is Number, the results are returned in numeric order. Otherwise, the results are returned in order of UTF-8 bytes. By default, the sort order is ascending. To reverse the order, set the ScanIndexForward parameter set to false.
Now, if you need to return all the items, you should use a scan. You cannot order the results of a scan.
Another option is to use a GSI (example). Here, you see that the GSI contains only HashKey. The results I guess will be in sorted order of this key (I didn't check this part in a program yet!).
As of now the dynamoDB scan cannot return you sorted results.
You need to use a query with a new global secondary index (GSI) with a hashkey and range field. The trick is to use a hashkey which is assigned the same value for all data in your table.
I recommend making a new field for all data and calling it "Status" and set the value to "OK", or something similar.
Then your query to get all the results sorted would look like this:
{
TableName: "YourTable",
IndexName: "Status-YourRange-index",
KeyConditions: {
Status: {
ComparisonOperator: "EQ",
AttributeValueList: [
"OK"
]
}
},
ScanIndexForward: false
}
The docs for how to write GSI queries are found here: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Querying
Approach I followed to solve this problem is by creating a Global Secondary Index as below. Not sure if this is the best approach but posting it if it is useful to someone.
Hash Key | Range Key
------------------------------------
Date value of CreatedAt | CreatedAt
Limitation imposed on the HTTP API user to specify the number of days to retrieve data, defaults to 24 hr.
This way, I can always specify the HashKey as Current date's day and RangeKey can use > and < operators while retrieving. This way the data is also spread across multiple shards.