【发布时间】:2022-11-17 00:46:04
【问题描述】:
所以,问题是,我正在尝试查询 DynamoDB 上的 GSI 表并得到一个非常奇怪的行为。 主表架构如下
- Partition key: test_id (string)
- Sort key: version (string)
- Other attributes (createdAt, tags, etc)
我想获取每个具有等于 v0_test 的 sort_key 的条目,而不按分区键过滤。为了做到这一点并避免全面扫描,我创建了一个 GSI(全球二级索引),如下所示:
- Partition key: version (string)
- Sort key: createdAt (number)
- Other attributes (test_id, tags, etc)
当从 AWS 控制台查询时,我可以查询每个等于 v0_test 的分区键,我得到了预期的结果,但是当我从 lambda 函数 (runtime: nodejs16.x) 内部查询时,我得到了一个错误。
查询代码如下:
const dynamoDb = new AWS.DynamoDB.DocumentClient();
let params = {
TableName: dynamoTable,
IndexName: dynamoTableIndex ,
KeyConditionExpression: 'version = :v0 AND createdAt BETWEEN :tLower AND :tUpper',
ExpressionAttributeValues: {
':v0': 'v0_test',
':tUpper': Math.floor(Date.now() / 1000).toString(),
':tLower': '0'
}
};
let result = await dynamoDb.query(params).promise();
console.log("Success", result);
我得到的错误是
ERROR ValidationException: Query condition missed key schema element: test_id
如您所见,它正在请求主表的分区键。
我尝试过的事情:
- 使用
AWS.DynamoDB而不是AWS.DynamoDB.DocumentClient。同样的错误 - 在查询中将
version更改为test_id。得到ERROR ValidationException: Query condition missed key schema element: version - 在
KeyConditionExpression上同时发送version和test_id。出现以下错误:ERROR ValidationException: KeyConditionExpressions must only contain one condition per key - 新的 Dynamodb 表,新的 GSI。同样的错误
我根本没想到。这是我第一次使用 DynamoDB,但据我了解,GSI(或其中之一)背后的想法是能够通过主分区键以外的其他属性查询 DynamoDB 表,而无需进行全面扫描。
任何帮助表示赞赏,如果您需要更多详细信息,请询问!这也是我第一次在 StackOverflow 上提问,所以我确定我会错过一些东西。
编辑
测试了建议的解决方案并收到一个错误提示模式错误,这是一个新错误并让我开始思考,所以我尝试指定 ExpressionAttributeNames 并且成功了!。
我使用 DocumentClient 创建了如下请求:
const dynamoDb = new AWS.DynamoDB.DocumentClient();
let params = {
TableName: 'CLASSIFIER_TESTS_DEV_us-east-1',
IndexName: 'version-createdAt-index',
KeyConditionExpression: '#versionAttr = :version AND #ca BETWEEN :tLower AND :tUpper',
ExpressionAttributeNames: {
"#versionAttr": "version",
"#ca": "createdAt"
},
ExpressionAttributeValues: {
":version": "v0_test",
":tUpper": Date.now(),
":tLower": 0
}
};
let result = await dynamoDb.query(params).promise();
感谢大家! 我仍然认为它应该像我第一次做的那样工作,因为这是每个人在教程/示例/文档中做的方式,但是哦,好吧,让它工作,这就是现在最重要的。
【问题讨论】:
-
真的好像你把一些名字弄混了。也许从控制台显示表和索引定义的屏幕截图?
-
您确定变量
dynamoTableIndex包含 GSI 的名称吗? -
@Charles 名字没问题。根据公司政策,我不能分享截图。我现在正在测试一些看起来很有希望的东西。如果我不能让它工作,我会用虚拟数据创建一个虚拟表并更新我的帖子
-
@MarkB 变量确实包含 GSI 的正确名称,但现在我正在使用硬编码的名称进行测试,以消除这种意义上的每个可能的错误。谢谢
标签: aws-lambda amazon-dynamodb serverless dynamodb-queries amazon-dynamodb-index