DynamoDB UPDATE if existing else PUT - Boolean - amazon-web-services

I need to have a table with the structure
{
userId : 123,
Tracking: true
}
It is possible that the user does not exist for the first operation. So, by default a false should be set. The next request makes this value true, 3rd request makes it false again and so on. Similar to NOT(Tracking) i.e writing a negation to the value.
I could do this by reading the table, negating the value in the my lambda function and updating the table with new attributes.
This would mean a GET and UPDATE request for the DB. I am looking for a way to send a negation flag instead. In this way I just write a false if the user is not existing. If the user is existing, I would toggle between true and false depending on the already existing boolean value.
Just wondering if there is a way to do this. It would be then a single update request to the DB. Any pointers would be helpful.
I did not find much help from the documentation https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#update-property

Instead of a boolean you can use an integer. Increment it by 1 each time and then use even as true, odd as false (or reversed)

Related

Is there any way to dump boolean object in Cloud BigTable?

I have certain usecase where api service are retrieving BigTable rows using rowKey. The issue I'm going through is api service is trying to retrieve some columns with boolean value and doing boolean comparison in front-end side. Since BigTable doesn't support that datatype. The front-end service comparison part is not working as expected. I'm using the below code to store boolean value in BigTable.
Boolean value = Boolean.parseBoolean(newImageMap.get(Key).toString());
SetCell setCell = SetCell.newBuilder()
.setFamilyName(Utility.COLUMN_FAMILY)
.setColumnQualifier(Utility.str_to_bb(Key,StandardCharsets.UTF_8))
.setTimestampMicros(yearAgoMillis)
.setValue(ByteString.copyFrom(Bytes.toBytes(value)))
// .setValue(Utility.str_to_bb(String.valueOf(value),StandardCharsets.UTF_8))
.build();
But the boolean value is stored as string in BigTable. You can see the stored value in below snapshot.
Let me know in case there is a way-out to handle this type of use-cases.
boolean-value-ss
so there are two parts to this: working with the existing boolean string values you have and converting the current setup to be easier to work with.
To work with the current setup, you can just compare your results against a "true" and "false" string. This seems to not be what you want to do based on your discussion in the comments with Pievis.
So to convert the current setup:
You should use 0 as false and 1 as true (or you can leave empty as false) This will be more efficient for space. And then to convert all of your existing values, you'd have to do a full table scan filtering on the value "true" and then update those cells to be 1 and one where you filter on the value "false" where you delete those cells.
Dumping boolean object in BigTable is not possible as BigTable doesn't support boolean datatype. Rather I will suggest you to make the changes in your driver code and type-case the datatype to suitable form and send it to front-end side, which would be more suitable. For that you have to pre-identify the boolean datatype from source end and stored it as configuration which will be an input to driver code.
Let me know in case this solution works.

DynamoDB column value reset to its initial value everyday

I have a table called 'Alunos' and one column called 'Presente' and it's a boolean value, which is set 'true'. And if a student didn't attend class, it changes to 'false'.
I need to know, how to make this value return 'true' automatically when changed the day.
Example: today is 9/10/19 and the value of the column is false. When it changes the day - 10/10/19 - it should return true. (its initial value)
How could I do that? Any tips?
Also, after doing that, I want to create a report or dashboard about this data, a monthly report for example. Do you have any tip for it as well?
Hope I made me clear.
Thanks
You should not change any existring value.
Here is what you should do.
Create 1 entry for everyday, with default value set to true or false.
Change the value based on user attendance.
Use enum instead of true/false.
This will make sure
You can see past trend.
you can have complex pattern like if holiday have new value than true and false.
If you are adamant on using single value per user, have a lambda function triggered by cloudwatch event everyday, which resets the value. But it will cause significant number of write everyday, instead of doing that you can check if value is expired and update only if expired.
this can solve your problem:
Time to Live (TTL) for Amazon DynamoDB lets you define when items in a table expire so that they can be automatically deleted from the database. TTL is provided at no extra cost as a way to reduce storage usage and reduce the cost of storing irrelevant data without using provisioned throughput.
and here is an example to set up TTL

Consistent implementation of modifying the same item in DynamoDB table by Multiple machines - multiple threads

I have an item (number) in DynamoDB table. This value is read in a service, incremented and updated back to the table. There are multiple machines with multiple threads doing this simultaneously.
My problem here is to be able to read the correct consistent value, and update with the correct value.
I tried doing the increment and update in a java synchronized block.
However, I still noticed inconsistencies in the count in the end. It doesn't seem to be updating in a consistent manner.
"My problem here is to be able to read the correct consistent value, and update with the correct value."
To read/write the correct consistent value
Read Consistency in dynamodb (you can set it in your query as ConsistentRead parameter):
There are two types of read.
Eventually Consistent Read: if you read data after changes in table, that might be stale and should wait a bit to be consistent.
Strongly Consistent Data: it returns most up-to-date data, so, should not be worried about the stale data
ConditionExpression (specify in your query):
in your query you can specify that update the value if some conditions are true (for example current value in db is the same as the value you read before. meaning no one updated it in between) otherwise it returns ConditionalCheckFailedException and you need to handle it in your code to redo, ...
So, to answer your question, first you need to ready strongly consistent to get the current counter value in db. Then, to update it, your query should look like this (removed unnecessary parameters) and you should handle ConditionalCheckFailedException in your code:
"TableName": "counters",
"ReturnValues": "UPDATED_NEW",
"ExpressionAttributeValues": {
":a": currentValue,
":bb": newValue
},
"ExpressionAttributeNames": {
"#currentValue": "currentValue"
},
**// current value is what you ve read
// by Strongly Consistent **
"ConditionExpression": "(#currentValue = :a)",
"UpdateExpression": "SET #currentValue = :bb", // new counter value
With every record store a uuid (long random string) sort of value, whenever you are trying to update the record send with update request which should update only if uuid is equal the the value you read. And update the uuid value.
synchronised block will not work if you are trying to write from multiple machines together.

Graceful handling of ConditionCheckFailedException with DynamoDB

When using ConditionExpression in a DynamoDB request, and the condition is not met, the entire request will fail. I am using conditional updates, and the fact that ConditionCheckFailedException doesn't contain any information about which condition failed is giving me a hard time.
For example consider this scenario: There's an item in a table like this:
{
state: 'ONGOING'
foo: 'FOO',
bar: 'BAR'
}
I then want to update this item, changing both foo and state:
ExpressionAttributeValues: {
:STATE_FINISHED: 'FINISHED',
:FOO: 'NEW FOO'
},
UpdateExpression: 'SET state=:STATE_FINISHED, foo=:FOO',
However, my application has a logical transition order of states, and to prevent concurrency issues where two requests concurrently modify an item and causing an inconsistent state, I add a condition to make sure only valid transitions of state are accepted:
ExpressionAttributeValues: {
:STATE_ONGOING: 'ONGOING'
},
ConditionExpression: 'state = :STATE_ONGOING'
This e.g. prevents two concurrent requests from modifying state into FINISHED and CANCELLED at the same time.
This is all fine when there's only one condition; if the request fails I know it was because an invalid state transition and I can choose whether to just fail the request, or to make a new request that only modifies FOO, whatever makes sense in my application. But if I have multiple conditions in one request, it seems impossible to find out which particular condition failed, which means I need to fail the entire request or divide it into multiple separate requests, updating one conditional value at a time. This can however raise new concurrency issues.
Has anyone found a decent solution to a similar problem?
Ideally what I'd want is to be able to make a UpdateExpression that modifies a certain attribute conditionally, otherwise ignoring it, or by using a custom function that returns the new value based on the old value and the suggested updated value, similar to an SQL UPDATE with an embedded SELECT .. CASE .... Is anything like this possible?
Or, is it at least possible to get more information out of a ConditionalCheckFailedException (such as which particular condition failed)?
As you mentioned, the DynamoDB doesn't provide granular level error message if there are multiple fields available on ConditionalExpression. I am not addressing this part of the question in my answer.
I would like to address the second part i.e. returning the old/new value.
The ReturnValues parameter can be used to get the desired values based on your requirement. You can set one of these values to get the required values.
New value - should already be available
Old value - To get old value, you can either use UPDATED_OLD or ALL_OLD
ReturnValues: NONE | ALL_OLD | UPDATED_OLD | ALL_NEW | UPDATED_NEW,
ALL_OLD - Returns all of the attributes of the item, as they appeared
before the UpdateItem operation.
UPDATED_OLD - Returns only the
updated attributes, as they appeared before the UpdateItem operation.
ALL_NEW - Returns all of the attributes of the item, as they appear
after the UpdateItem operation.
UPDATED_NEW - Returns only the updated
attributes, as they appear after the UpdateItem operation.

Is it possible to use a XSLT to check if a string is Null/ Empty

I'm doing a workflow for a SharePoint site that is taking data from another SharePoint sites list and then putting it into the new site, I have this bit working fine but I have a issue where it seems to be updating both lists due to one of the logic operations thinking that a value is not null. My question is would it be possible to use an XSLT to set a sort of Boolean that will return True when a string == Null? and if so could you give me some pointers on how to get started with this?
not ($yourString)
will return True if the string is empty, False otherwise. Not sure what "null" means in this context