如何在serverless.yaml中定义DynamoDB排序键及实现数据排序
Hey there! Let's start with a key clarification: DynamoDB doesn't support having multiple sort keys on a single primary table. The primary key can either be a simple partition key (like your existing id) or a composite key (one partition key + one sort key). To sort by multiple fields (Fullname and Email in your case), you'll need to use Global Secondary Indexes (GSIs)—these act like separate "virtual tables" that let you query and sort based on different key combinations.
Step 1: Update Your Serverless.yaml to Add GSIs
Here's how to modify your existing configuration to add two GSIs: one for sorting by Fullname, and another for sorting by Email. We'll also add the necessary attribute definitions for these fields:
resources: Resources: UserDynamoDbTable: Type: 'AWS::DynamoDB::Table' DeletionPolicy: Retain Properties: AttributeDefinitions: - AttributeName: id AttributeType: S - AttributeName: Fullname AttributeType: S - AttributeName: Email AttributeType: S # Virtual partition key to enable global sorting across all users - AttributeName: globalSortKey AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 TableName: 'user' GlobalSecondaryIndexes: # GSI for sorting by Fullname - IndexName: FullnameSortIndex KeySchema: - AttributeName: globalSortKey KeyType: HASH - AttributeName: Fullname KeyType: RANGE Projection: ProjectionType: ALL # Projects all table attributes to the index ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 # GSI for sorting by Email - IndexName: EmailSortIndex KeySchema: - AttributeName: globalSortKey KeyType: HASH - AttributeName: Email KeyType: RANGE Projection: ProjectionType: ALL ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1
What's Changed?
- AttributeDefinitions: Added
Fullname,Email, andglobalSortKey(a dummy partition key to group all users together for global sorting—set this to a consistent value like"user"when inserting records). - GlobalSecondaryIndexes: Two indexes, each with:
IndexName: A unique identifier to reference when querying.KeySchema: UsesglobalSortKeyas the partition key (so we can fetch all users) and your target field (Fullname/Email) as the sort key.ProjectionType: ALL: Ensures all user attributes are available in the index (useKEYS_ONLYorINCLUDEfor better efficiency if you don't need every field).
Step 2: Querying Data with ASC/DESC Sort Order
When fetching data in your Lambda function, use the DynamoDB Query API, specify the index name, and use the ScanIndexForward parameter to control sort direction:
Example (JavaScript with AWS SDK v3):
const { DynamoDBClient, QueryCommand } = require("@aws-sdk/client-dynamodb"); const { unmarshall } = require("@aws-sdk/util-dynamodb"); const client = new DynamoDBClient({ region: "your-region" }); // Fetch users sorted by Fullname (ASC or DESC) async function getUsersSortedByFullname(sortOrder = "ASC") { const params = { TableName: "user", IndexName: "FullnameSortIndex", KeyConditionExpression: "#gsk = :gskVal", ExpressionAttributeNames: { "#gsk": "globalSortKey" }, ExpressionAttributeValues: { ":gskVal": { S: "user" } }, // Match your globalSortKey value ScanIndexForward: sortOrder === "ASC" // true = ascending, false = descending }; const command = new QueryCommand(params); const response = await client.send(command); // Convert DynamoDB-formatted items to plain JavaScript objects return response.Items.map(item => unmarshall(item)); } // Fetch users sorted by Email async function getUsersSortedByEmail(sortOrder = "ASC") { const params = { TableName: "user", IndexName: "EmailSortIndex", KeyConditionExpression: "#gsk = :gskVal", ExpressionAttributeNames: { "#gsk": "globalSortKey" }, ExpressionAttributeValues: { ":gskVal": { S: "user" } }, ScanIndexForward: sortOrder === "ASC" }; const command = new QueryCommand(params); const response = await client.send(command); return response.Items.map(item => unmarshall(item)); }
Key Notes:
ScanIndexForward: Set totruefor ascending order (A-Z, 0-9) andfalsefor descending (Z-A, 9-0).- When inserting user records, always include the
globalSortKeyattribute with the same value (e.g.,"user") to ensure all users are grouped under the same partition in the GSIs—this lets you query all users sorted by your target field.
内容的提问来源于stack exchange,提问作者Akib Deraiya

