I have written some python code, I want to query dynamoDB data by sort key. I remember I can use follow-up code successful:
table.query(KeyConditionExpression=Key('event_status').eq(event_status))
My table structure column
primary key:event_id
sort key: event_status
Query results are always sorted by the sort key value. If the data type of the sort 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 to false.
The sort key of an item is also known as its range attribute. The term range attribute derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value. Each primary key attribute must be a scalar (meaning that it can hold only a single value).
Hash key in DynamoDB The primary reason for that complexity is that you cannot query DynamoDB without the hash key. So, it's not allowed to query the entire database. That means you cannot do what you would call a full table scan in other databases.
Generally in DynamoDB you can create Local Secondary Indexes if you need alternative sort key: To give your application a choice of sort keys, you can create one or more local secondary indexes on an Amazon DynamoDB table and issue Query or Scan requests against these indexes.
You have to create a global secondary index (GSI) for the sort key in order to query on it alone.
The scan API should be used if you would like to get data from DynamoDB without using Hash Key attribute value.
Example:-
fe = Attr('event_status').eq("new");
response = table.scan(
FilterExpression=fe
)
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
while 'LastEvaluatedKey' in response:
response = table.scan(
FilterExpression=fe,
ExclusiveStartKey=response['LastEvaluatedKey']
)
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
If you don't want to scan (and maybe you shouldn't), you will need to create a GSI (Global Secondary Index) for that, and set event_status
as the GSIPK.
so your table config will be:
table = dynamodb.create_table(
TableName="your_table",
KeySchema=[
{"AttributeName": "event_id", "KeyType": "HASH"}, # Partition key
{"AttributeName": "event_status", "KeyType": "RANGE"}, # Sort key
],
AttributeDefinitions=[
{"AttributeName": "event_id, "AttributeType": "S"},
{"AttributeName": "event_status", "AttributeType": "S"},
{"AttributeName": "event_status", "AttributeType": "S"},
{"AttributeName": "event_id", "AttributeType": "S"},
],
GlobalSecondaryIndexes=[
{
"IndexName": "gsiIndex",
"KeySchema": [
{"AttributeName": "event_status", "KeyType": "HASH"},
{"AttributeName": "event_id", "KeyType": "RANGE"},
],
"Projection": {"ProjectionType": "ALL"},
},
],
BillingMode="PAY_PER_REQUEST",
)
Be mindful that GSIs can be expensive and you might wanna change the ProjectionType if you don't need all attributes.
Now you can query by pk:
table.query(KeyConditionExpression=Key('event_id').eq(event_id))
or by the GSI PK which is set to your sk:
lookup.query(
IndexName="gsiIndex",
KeyConditionExpression=Key("event_status").eq(event_status),
)
According to the main concept of the sort key, it is part of main cluster in the partition key to define some filter expression with partition key in query. so there is no ability to search on the sort key alone and without partition key. unless to define a global secondary index on the sort key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With