What will happen if I create a PutItem request like this:
{
"Expected":
{
"testAttribute" :
{
"Exists": "false",
}
},
"Item":
{
"testAttribute" :
{
"S": "testValue"
}
},
"TableName": "TableName"
}
where "testAttribute" is not part of the primary key.
Will DynamoDB scan the table to see if there is an item with attribute "testAttribute" == "testValue" ?
If not, how will DynamoDB determine the presence of a "testAttribute" == "testValue" ?
I can't find anything in the docs describing how this works.
According to the documentation of the PutItem action, you are not allowed to issue that request. It says:
Item: A map of attribute name/value pairs, one for each attribute. Only the primary key attributes are required; you can optionally provide other attribute name-value pairs for the item.
(emphasis mine)
You must provide a value for each attribute of the primary key whenever you use PutItem.
This way, as you will surely agree, it is very simple and fast for DynamoDB to check the condition you defined on the Expected clause: no scan is needed, it just has to look at the single item that could match the request. Otherwise, as you noted, DynamoDB would need to perform a full table scan (and it would possibly be very slow, and they would certainly charge you for that) or it would need to maintain a consistent index of every single item in a table, and they would charge you for the SSD space used to store it!
Also, note that the meaning of the expected clause is a little bit different than what you described in the question. Supposing you fix your request and add all the primary key attributes, the request would mean:
"If the item identified by this primary key does not exist, create it; if it does exist and does not contain an attribute named testAttribute, replace the item with the one whose attributes are described in this request; if the item does exist and does contain an attribute named testAttribute, do nothing".
Your description says that DynamoDB would check if the value of testAttribute is testValue, but it is not what happens when you use the Expected/Exists clause. To achieve the effect you described, you need to use the Expected/Value clause, and then you specify the value you are expecting in that clause -- the value specified for the attribute in the Item property of the request is just used to define the new value of the attribute, if an update (or insert) is to occur.
Related
I've got an object like this:
{
"id": (UUID generated at call time)
"referenceId": (Foreign key for another system)
"referenceType": (enum)
}
The primary index is just
Primary key: id
And I've got a secondary index like
Primary key: referenceId
Secondary key: referenceType
So what I want to do, is query the secondary index with the referenceId and referenceType, and then if that's empty, write the record to the table.
The problem is, Conditional Expressions can only check same index you're querying. And I've looked into DynamoDb Transactions, but they say you can't have two transactions target the same item.
Is there a way to make this work?
If I understand your question correctly, your item has three attributes: id,
referenceId and referenceType. You've also defined a global secondary index with a composite primary key of referenceId and referenceType.
Assuming all these attributes are part of the same item, you shouldn't need to read the secondary index before deciding to write to the table. Rather, you could perform a PUT operation on the condition that referenceId and reference type don't yet exist on that item.
ddbClient.putItem({
"TableName": "YOUR TABLE NAME",
"Item": { "PK": "id" },
"ConditionExpression": "attribute_exists(referenceId) AND attribute_exists(referenceType)"
})
You may also want to check out this fantastic article on DynamoDB condition expressions.
As I understand the question, your table PK is generated "at call time" so it would be different for two different requests with the same reference ID and reference type.
That being the case, your answer is no.
If you've got a requirement for uniqueness of a key set by a foreign system, you should consider using the same key or some mashup of it for your DDB table.
Alternately, modify the foreign system to set the UUID for a given reference ID & type.
I am confused what to make my CosmosDB partition key when my JSON looks like this
{
"AE": [
{
"storeCode": "XXX",
"storeClass": "YYY"
}
],
"AT": [
{
"storeCode": "ZZZ",
"storeClass": "XYZ"
}
]
}
Normally the top level would be country:AT and so on and I would make the partition key /country but in this case I have nothing to use on the top level so what do I do?
the JSON comes from a third party so I dont have the option to change it at source.
Since i did not find any statements about the partition key for sub-array in the official document. I could only provide you with a similar thread for your reference :CosmosDB - Correct Partition Key
Here is some explanations by #Mikhail:
Partition Key has to be a single value for each document, it can't be
a field in sub-array. Partition Key is used to determine which
database node will host your document, and it wouldn't be possible if
you specified multiple values, of course.
If your single document contains data from multiple entities, and you
will query those entities separately, it might make sense to split
your documents per entity. If all those "radars" are related to some
higher level entity, use that entity ID as partition key.
For rigor,i would suggest you contacting with azure cosmos team to check whether this feature is not supported yet so far,whether will be implemented in the future.
I have table with "RefNumber", "status" and "Date". "RefNumber" is the partition Key and "Status" is the sort key So, both make a primary key.
{
"RefNumber": "122345",
"Status": "0",
"DateTime": 15343354545
}
Now after fetching this record, I want to update "Status" with "1". I have multiple workers reading the DynamoDB records, just to avoid any 2 workers processing the same record I want to fetch and update the "Status" with "1" using ConditionExpression, if the update succeeds the worker will process else it will skip.
My question is, is it a good design to update the attribute value which is part of the primary key in dynamodb
The short answer is No, it is not possible to update an attribute that forms the Key of an item in DynamoDB.
You can only delete the item and create another one.
If you consider this, logically, modifying a key of an element doesn’t make any sense: an element is uniquely identified by it’s key, so what does it even mean that you’re mutating the key? It would mean the old element is replaced entirely.
DynamoDB does not offer an atomic “replace” operation.
Suppose I have an object like
{
epochTime : 1527174282
action : create
state : fail
}
From the documentation of AWS, to query
You must specify the partition key name and value as an equality
condition.
You can optionally provide a second condition for the sort key (if
present).
In the case where I just want to query some item from A to B from the whole dataset ( Just want to use the sort key ) how should I chooe the hash key and query for this kind of data to work effectively?
You need to define secondary index for the attribute with the primary key (hash) as the field and perform scan on the secondary index
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html
Working with scans
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html
Also refer this java sdk examples for working with secondary index and scans https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSIJavaDocumentAPI.Example.html
https://aws.amazon.com/about-aws/whats-new/2015/02/10/secondary-index-scan-a-simpler-way-to-scan-dynamodb-table/
I'm trying to create an index on a nested field, using the Dashboard in AWS Developer Console. E.g. if I have the following schema:
{ 'id': 1,
'nested': {
'mode': 'mode1',
'text': 'nice text'
}
}
I was able to create the index on nested.mode, but whenever I then go to query by index, nothing ever comes back. It makes me think that DynamoDB created the index on a field name nested.mode instead of the mode field of nested. Any hints re. what I might be doing wrong?
You cannot (currently) create a secondary index off of a nested attribute. From the Improving Data Access with Secondary Indexes in DynamoDB documentation (emphasis mine):
For each secondary index, you must specify the following:
...
The key schema for the index. Every attribute in the index key schema must be a top-level attribute of type String, Number, or Binary. Nested attributes and multi-valued sets are not allowed. Other requirements for the key schema depend on the type of index:
You can, however, create an index on any top level JSON element.