如何在DynamoDB中创建带有索引属性的条目?
解决DynamoDB创建条目时索引属性无法查询的问题
你的核心问题是没有提前在表中定义对应的二级索引,所以直接写入date和timestamp只会被当作普通属性,无法通过索引查询。下面是具体的解决步骤和JS代码示例:
1. 先创建/更新表,添加二级索引
DynamoDB的二级索引(全局GSI/局部LSI)必须先在表结构中定义,才能让对应的属性成为索引字段。
示例1:创建表时同时定义全局二级索引
如果你的表还没创建,可以在创建时直接加入索引:
const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB({ region: '你的区域' }); const createTableParams = { TableName: 'Posts_Table', // 表的主键定义 KeySchema: [ { AttributeName: 'username', KeyType: 'HASH' }, { AttributeName: 'image_id', KeyType: 'RANGE' } ], // 所有需要用到的属性类型定义(包括索引属性) AttributeDefinitions: [ { AttributeName: 'username', AttributeType: 'S' }, { AttributeName: 'image_id', AttributeType: 'S' }, { AttributeName: 'date', AttributeType: 'S' }, // 索引属性的类型 { AttributeName: 'timestamp', AttributeType: 'N' } ], // 定义全局二级索引 GlobalSecondaryIndexes: [ { IndexName: 'DateTimestampIndex', // 索引名称,查询时要用到 KeySchema: [ { AttributeName: 'date', KeyType: 'HASH' }, // 索引的Hash键 { AttributeName: 'timestamp', KeyType: 'RANGE' } // 索引的Range键 ], Projection: { ProjectionType: 'ALL' // 投影所有属性到索引,也可以指定具体属性 }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } } ], ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } }; dynamodb.createTable(createTableParams, (err, data) => { if (err) console.error('创建表失败:', err); else console.log('表创建成功:', data); });
示例2:给已存在的表添加全局二级索引
如果表已经创建好,可以通过更新表来添加索引:
const updateTableParams = { TableName: 'Posts_Table', AttributeDefinitions: [ { AttributeName: 'date', AttributeType: 'S' }, { AttributeName: 'timestamp', AttributeType: 'N' } ], GlobalSecondaryIndexUpdates: [ { Create: { IndexName: 'DateTimestampIndex', KeySchema: [ { AttributeName: 'date', KeyType: 'HASH' }, { AttributeName: 'timestamp', KeyType: 'RANGE' } ], Projection: { ProjectionType: 'ALL' }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } } } ] }; dynamodb.updateTable(updateTableParams, (err, data) => { if (err) console.error('更新表失败:', err); else console.log('表更新成功:', data); });
2. 插入数据并使用索引查询
当索引创建完成后,你之前的插入代码完全可以用——只要Item包含索引的键属性,DynamoDB会自动把数据同步到索引中。之后查询时需要指定索引名称:
插入数据(你的原代码可以直接用)
const docClient = new AWS.DynamoDB.DocumentClient({ region: '你的区域' }); const params = { TableName: 'Posts_Table', Item: { 'username': user, 'image_id': uuid(), 'date': date, 'timestamp': timestamp } }; docClient.put(params, (err, data) => { if (err) console.error('插入失败:', err); else console.log('插入成功:', data); });
通过索引查询数据
const queryParams = { TableName: 'Posts_Table', IndexName: 'DateTimestampIndex', // 指定要使用的索引名称 KeyConditionExpression: '#dt = :targetDate', ExpressionAttributeNames: { '#dt': 'date' }, // 避免关键字冲突 ExpressionAttributeValues: { ':targetDate': '2024-05-20' } // 要查询的日期值 }; docClient.query(queryParams, (err, data) => { if (err) console.error('查询失败:', err); else console.log('查询结果:', data.Items); });
关键注意点
- 局部二级索引(LSI)必须和表一起创建,不能事后添加,且LSI的Hash键必须和表的Hash键一致,只能指定不同的Range键。
- 索引创建/更新需要一段时间,完成后才能查询到新插入的数据。
- 投影类型选择
ALL会把所有属性同步到索引,适合小数据量;如果数据量大,建议只投影需要查询的属性,节省存储和读写成本。
内容的提问来源于stack exchange,提问作者henry
相关产品推荐
相关产品推荐

