#2760 - DynamoDB - Ensure proper ordering for Numeric sort keys

This commit is contained in:
Bert Blommers 2020-03-17 16:28:49 +00:00
parent 60c98ca836
commit 67c7fce85e
2 changed files with 64 additions and 1 deletions

View File

@ -981,8 +981,13 @@ class Table(BaseModel):
if index_name:
if index_range_key:
# Convert to float if necessary to ensure proper ordering
def conv(x):
return float(x.value) if x.type == "N" else x.value
results.sort(
key=lambda item: item.attrs[index_range_key["AttributeName"]].value
key=lambda item: conv(item.attrs[index_range_key["AttributeName"]])
if item.attrs.get(index_range_key["AttributeName"])
else None
)

View File

@ -4026,3 +4026,61 @@ def test_valid_transact_get_items():
"Table": {"CapacityUnits": 2.0, "ReadCapacityUnits": 2.0,},
}
)
@mock_dynamodb2
def test_gsi_verify_negative_number_order():
table_schema = {
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
"GlobalSecondaryIndexes": [
{
"IndexName": "GSI-K1",
"KeySchema": [
{"AttributeName": "gsiK1PartitionKey", "KeyType": "HASH"},
{"AttributeName": "gsiK1SortKey", "KeyType": "RANGE"},
],
"Projection": {"ProjectionType": "KEYS_ONLY",},
}
],
"AttributeDefinitions": [
{"AttributeName": "partitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1PartitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1SortKey", "AttributeType": "N"},
],
}
item1 = {
"partitionKey": "pk-1",
"gsiK1PartitionKey": "gsi-k1",
"gsiK1SortKey": Decimal("-0.6"),
}
item2 = {
"partitionKey": "pk-2",
"gsiK1PartitionKey": "gsi-k1",
"gsiK1SortKey": Decimal("-0.7"),
}
item3 = {
"partitionKey": "pk-3",
"gsiK1PartitionKey": "gsi-k1",
"gsiK1SortKey": Decimal("0.7"),
}
dynamodb = boto3.resource("dynamodb")
dynamodb.create_table(
TableName="test-table", BillingMode="PAY_PER_REQUEST", **table_schema
)
table = dynamodb.Table("test-table")
table.put_item(Item=item3)
table.put_item(Item=item1)
table.put_item(Item=item2)
resp = table.query(
KeyConditionExpression=Key("gsiK1PartitionKey").eq("gsi-k1"),
IndexName="GSI-K1",
)
# Items should be ordered with the lowest number first
[float(item["gsiK1SortKey"]) for item in resp["Items"]].should.equal(
[-0.7, -0.6, 0.7]
)