I'm trying to use the query expression an getting
ATTEMPT EDIT - 1 PASS
An error occurred (ValidationException) when calling the Query operation: Invalid KeyConditionExpression: Syntax error; token: "{", near: "{""
This query looks like
aws dynamodb query --table-name name-of-table --key-condition-expression 'id=:91'
I've tried '"id"="91"', ':id=":91"', etc.
id is the partition key so this is also the required attribute needed.
Try this
aws dynamodb query --table-name name-of-table --key-condition-expression 'id = :idval' --expression-attribute-values '{":idval":{"S":"91"}}'
You have to use value substitution on attributes. You can optionally use attribute name substitution.
Note i've assume your id attribute is of type String. Change it to "N" if its a number.
Related
I want to do conditional putItem call into DynamoDb i.e. don't insert an entry in dynamoDb if the primaryKey(partitionKey + Sort Key already exists). My schema's key look like this:
PartitionKey: abc:def
SortKey:abc:123
To do a conditional I do something like this:
private static final String PK_DOES_NOT_EXIST_EXPR = "attribute_not_exists(%s)";
final String condition = String.format(PK_DOES_NOT_EXIST_EXPR,
record.getPKey() + record.getSortKey);
final PutItemEnhancedRequest putItemEnhancedRequest = PutItemEnhancedRequest
.builder(Record.class)
.conditionExpression(
Expression.builder()
.expression(condition)
.build()
)
.item(newRecord)
.build();
However I run into following error
Exception in thread "main" software.amazon.awssdk.services.dynamodb.model.DynamoDbException: Invalid ConditionExpression: Syntax error; token: ":123", near: "abc:123)" (Service: DynamoDb, Status Code: 400
I am assuming this is because of : present in my condition, because the same expression without : in the key succeeds. Is there a way to fix this?
Your condition should include the name of the partition key attribute, not its value. For example:
attribute_not_exists(pk)
Also, see Uniqueness for composite primary keys for an explanation of why you only need to indicate the partition key attribute name, not both the partition key and the sort key attribute names. So, the following, while not harmful, is unnecessary:
attribute_not_exists(pk) AND attribute_not_exists(sk)
I want to create a DynamoDB table which contains only one order entity with following attributes:
OrderId
OrderStatus
Price
Access patterns I try to achieve:
Get single order by id
Filter orders by status
Design in my mind for above access patterns is to create simple primary key consisting of OrderId and one local secondary index with composite primary key consisting of OrderId and OrderStatus. AWS CLI command for achieving this:
aws dynamodb create-table \
--table-name Order \
--attribute-definitions \
AttributeName=OrderId,AttributeType=S \
AttributeName=OrderStatus,AttributeType=S \
--key-schema \
AttributeName=OrderId,KeyType=HASH \
--local-secondary-indexes \
"[{\"IndexName\": \"OrderStatusIndex\",
\"KeySchema\":[{\"AttributeName\": \"OrderId\",\"KeyType\":\"HASH\"},
{\"AttributeName\":\"OrderStatus\",\"KeyType\":\"RANGE\"}],
\"Projection\":{\"ProjectionType\":\"INCLUDE\", \"NonKeyAttributes\":[\"Price\"]}}]" \
--provisioned-throughput \
ReadCapacityUnits=1,WriteCapacityUnits=1 \
--table-class STANDARD
When running this command, I get:
An error occurred (ValidationException) when calling the CreateTable
operation: One or more parameter values were invalid: Table KeySchema
does not have a range key, which is required when specifying a
LocalSecondaryIndex
How can get rid of this error while sticking to my design? Or if it is not possible how should I design my table in this case?
The definition of a Local Secondary index is that it has the same Partition Key as the table , but a difference range key.
In order to have a partition key other than what the table uses, you'll need a Global Secondary Index.
I wanted to run a greater than Query against the primary key of my table. Later I came to know that greater than queries can only be executed on sort keys, and not on primary keys. So, I have now re-designed my table, and here's a screenshot of the new it : (StoreID is the Primary key, & OrderID is the Sort key)
How should I format the Query, if I want to run a query like return those items whose 'OrderID' > 1005?
More particularly, what should I mention in the Query condition to meet my requirements?
Thanks a lot!
You can use the following CLI command to run query "return those items in store with storeid='STR100' whose 'OrderID' > 1005".
aws dynamodb query --table-name <table-name> --key-condition-expression "StoreID = :v1 AND OrderID > :v2" --expression-attribute-values '{":v1": {"S": "STR100"}, ":v2": {"N": 1005}}'
I need to design a DynamoDB schema to store items whose attributes are:
tid: a UUID string which is a unique identifier of the item
timestamp: an ISO-8601-formatted string representing a date and time related to the item
Other stuff...
and for the following query (really want to avoid having to do any scans) patterns:
Query by tid
Query by exact timestamp, and by relational ordering expressions (e.g., <=, BETWEEN, etc.) on timestamp. I.e., query all items from a certain date-time range without knowing their tids in advance.
Is this possible to do efficiently in DynamoDB, or is there perhaps another AWS solution that would serve me better?
Given a DynamoDB table as follows:
partition key: tid, type string
sort key: timestamp, type string
You can query on:
tid = 5
tid = 5, timestamp between 2018-12-21T09:00:00Z and 2018-12-21T15:00:00Z
Try it out using the awscli, for example to query all items with tid=5:
aws dynamodb query \
--table-name mytable \
--key-condition-expression "tid = :tid" \
--expression-attribute-values '{":tid":{"S":"5"}}'
To query all items for tid=5 and timestamp between 09:00 and 15:00 on 2015-12-21:
aws dynamodb query \
--table-name mytable \
--key-condition-expression "tid = :tid AND #ts BETWEEN :ts1 AND :ts2" \
--expression-attribute-values '{":tid":{"S":"5"}, ":ts1":{"S":"2015-12-21T09:00:00Z"}, ":ts2":{"S":"2015-12-21T15:00:00Z"}}' \
--expression-attribute-names '{"#ts":"timestamp"}'
Note: because timestamp is a reserved keyword in DynamoDB, you have to escape it using the expression attribute names.
You could also create the timestamp attribute as a number and then store epoch times, if you prefer.
To query all items with timestamp between 09:00 and 15:00 on 2015-12-21, regardless of tid, cannot be done with the same partition/sort key schema. You would need to add a Global Secondary Index something like this:
GSI partition key: yyyymmdd, type string
GSI sort key: timestamp, type string
Now you can query for items with a given timestamp range, as long as they're on the same day (they have the same YYYYMMDD, which might be a reasonable restriction). Or you could go to YYYYMM as the partition key allowing a wider timestamp range. At this point you really need to understand the use cases for queries to decide if YYYYMMDD (restricting queries to a single day) is right. See How to query DynamoDB by date with no obvious hash key for more on this idea.
i'm trying to query a number field in DynamoDB through aws-cli.
It forces me to set the key (userId) to be something, although I want to retrieve all the users where the queriedField equals to 0. this is the syntax:
aws dynamodb query
--table-name TableName
--key-condition-expression "userId = :userid"
--filter-expression "mapAttr.queriedField = :num"
--expression-attribute-values '{ ":userid": { "S": "<AccountID>" }, ":num" : { "N": "0" }}'
In order to do this query, you will have to scan the whole table with your filter expression.
However, if this is for something that is still in development/design, consider making the 'number field' a top level attribute. That will allow you to create a GSI with a hash key of 'number field', and project the userId attribute to the GSI. Alternatively, you can use Global Secondary Index Write Sharding for Selective Table Queries