DynamoDb map vs string attribute read /update - amazon-dynamodb

I have a dynamodb table where partition key is userid uniformly distributed. Table store data about User information like(name , email,country, and portal cards the user hold- say user1 has cards1,cards2,cards3 (max 10 category of cards) with detail of cards1 as (gold card,purchased date-yyyy-mm-dd).A user can have Queries on table will be by userid.
I need to get how many cards with name and type user1 hold,
need to get country of user1
Need to get does user1 hold any card of card1 category of gold type
hold ,which were purchased in current year and whats the country of
user1.
To achieve this I can design my schema in 2 ways:-
Each item has attributes(other than userid partition key) as (Country-string,name string,email string,cards
map{"card1":{"purchasedate":"yyyy-mm-dd","type":"gold"},"card2":{{"purchasedate":"yyyy-mm-dd","type":"platinum"}}}
Make userid as primary key and card category as sort key and keep user info in item with key as userid_all and card info in item with
key as userid_card1 and attributes of string type as purchasedate
and type. say userid1_all : country:Us,email:abc#abc.com
userid_card1: purchasedate:yyyy-mm-dd,type:gold
Which approach is better ?
Reading data from map attribute is better or from string attribute.
Updating attributes with map type(say userid1 for card1 type is upgraded from gold to platinum) is better or string type.
Thanks

Though DynamoDB supports Document data types (Map, List etc), the query API is not very robust. In your design approach 1, if you convert the data into DynamoDB item, you will actually end up with complex object (i.e. card1 value is an object with two attributes purchasedate and type) for cards attribute. The third query pattern has the requirement to filter by purchasedate and type which DynamoDB API doesn't support as it is inside another object of MAP data type rather than some scalar attribute inside MAP.
Simple object of MAP:-
{"purchasedate":"yyyy-mm-dd","type":"gold"}
Complex object of MAP:-
{"card1":{"purchasedate":"yyyy-mm-dd","type":"gold"},"card2":{"purchasedate":"yyyy-mm-dd","type":"platinum"}}
So, the design approach 2 is better. As long as you have scalar attributes (i.e. String, Number, Boolean), you can query the table by different combinations of attributes in FilterExpression.

Related

What's the best way to store users in DynamoDB so I can get one efficiently, and a related group as well?

I have users for my website that need to log in. In order to do that, I have to check the database for them, by email address or a hash of their email.
Some of my users have an online course in common.
Others are all on the same project.
There are multiple projects and courses.
How might I set up my table so that I can grab individual users, and efficiently query related groups of users?
I'm thinking...
PK = user#mysite
SK = user#email.com
projects = [1,2,3]
courses = [101,202,303]
I can get any user user with a get PK = user#mysite, SK = user#email.com.
But if I query, I have to filter two attributes, and I feel like I'm no longer very efficient.
If I set up users like this on the other hand:
PK = user#email.com
SK = 1#2#3#101#202#303
projects = [1,2,3]
courses = [101,202,303]
Then I can get PK = user#gmail.com and that's unique on its own.
And I can query SK contains 101 for example if I want all the 101 course students.
But I have to maintain this weird # deliminated list of things in the SK string.
Am I thinking about this the right way?
You want to find items which possess a value in an attribute holding a list of values. So do I sometimes! But there is not an index for that.
You can, however, solve this by adding new items to the table.
Your main item would have the email address as both the PK and the SK. It includes attributes listing the courses and projects, and all the other metadata about that user.
For each course, you insert additional items where the course id is the PK and the member emails are the various SKs in that item collection. Same for projects.
Given an email, you can find all about them with a get item. Given a course or project you can find all matching emails with a query against the course or project id. Do a batch get items then if you need all the data about each email.
When someone adds or drops a course or project, you update the main item as well as add/remove the additional indexed items.
Should you want to query by course X and project Y you can pull the matching results to the client and join in the client on email address.
In one of your designs you're proposing a contains against the SK, which is not a supported operator against SKs so that design wouldn't work.

Firestore and flutter: update documents when a field is null

I have a collection which represents a list of available sport matches (see image below, sorry for the italian text).
Each document is a match, and has a list of players which are subscribed to that match (id_player1, id_player2, etc).
When someone would like to subscribe to that match, I have to cycle through the players_id, and when I find a null one, I set it to the user's id.
So my questions are:
how can I cycle through the fields of the document and check if they are null or not?
how can I count how many fields are not null, so when this count is equal to X, I do something?
You decide to define 6 different fields to store players id.. so u cannot cycle that fields.. what you can do is to get all of the six fileds and check one by one if they are null...
what you should do is to refactor that logic and store players id in a collection.. an update the collection only if its count is under 6 so you haven't t check if you have any space left to add player id
Bye :D
If there is no specific meaning to each individual id_player* field, consider storing all player IDs in a single player_ids array field.
That way you can use arrayUnion to add values to the field (preventing duplicates) and query with array_contains to find documents with a specific player ID.

How do I model this in DynamoDB?

I am testing out DynamoDB for a serverless app I am building. I have successfully modeled all of my application's query patterns except one. I was hoping someone could provide some guidance. Here are the details:
Data Model
There are three simple entities: User (~1K records), Product (~100K), ActionItem (~100/product).
A User has a many-to-many relationship with Product.
A Product has a one-to-many relationship with ActionItem.
The Workflow
There's no concept of "Team" for this app. Instead, a user is assigned a set of products which they (and others) are responsible for managing. The user picks the oldest items from their products' action item list, services the item and then closes it.
The use case I am trying to model is: As a user, show me all action items for products to which I am assigned.
Any help would be greatly appreciated.
Really only two options...
If you can store the list of products within the 400KB limit of DDB record, then you could have a record like so...
Hash Key: userID
Sort KEY: "ASSIGNED_PRODUCTS"
Otherwise,
Hash key: UserID
Sort key: "#PRODUCT#10001-54502"
userID in the above might be the raw userid, or if using a GSI, might be something like "#USER#user-id"

GQL Projection Query on Embedded Entity

Say I have a User entity with an embedded entity address which contains a house number property and a street property. How can I write a GQL projection query that will filter based on name and return a list of addresses ?
Sample Data:
The projection query I am trying to write:
SELECT address FROM User WHERE name = Bob
This should return two addresses but it returns no results.
Thanks to anyone who answers !
You can't project the entire entity value, but you can project the individual properties in the entity value, e.g.:
SELECT address.houseNumber FROM User WHERE name = Bob

can you create indexes on embedded objects in dynamodb

Coming from a mongodb background, I'd like to set up a document with an embedded collection.
For instance if I have a profile object
Profile
name : string
followers : [
name: string
]
such that it has an embedded collection of followers.
Is there a way that I can create an index on Profile so that I can query for all profiles where Profile.Followers includes myUsername?
In short I can query for profiles I'm following from a dynamoDB table?
In mongo I can easily do this by setting up an index on Profile.followers and doing an $in query. Is there something similar for dynamodb?
This documentation suggests there is nothing like an in clause
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html
Currently DynamoDB does not support indices for non scalar types (i.e. Set, List, or Map data types - see here: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html). If you have a separate users table, you can keep track of all profiles you are following in a Set/List attribute.

Resources