TypeScript中从DynamoDB查询Filter表达式提取键值对方法
问题解决:正确生成DynamoDB的ExpressionAttributeValues
错误原因
你的Filter表达式结构是每个字段对应一个包含操作符(如eq)的对象(比如{"Age":{"eq":3}}),但现有代码错误地把整个{"eq":3}对象当成了字段值,导致生成的ExpressionAttributeValues出现了{":Age":{"S":{"eq":3}}}这种嵌套的错误结构,DynamoDB无法识别这种格式。
DynamoDB要求ExpressionAttributeValues的结构是占位符对应值类型对象,比如数字类型用{N: "3"},字符串类型用{S: "MALE"},不需要包含操作符(操作符已经写在FilterExpression里)。
修正代码
1. 修正FilterExpression生成逻辑
需要从每个条件中提取操作符,生成正确的过滤表达式:
getFilterExpression(filter: Record<string, Record<string, any>>) { const expressions = []; Object.entries(filter).forEach(([key, condition]) => { const expressionKey = `#${key}`; const expressionValue = `:${key}`; // 提取操作符(比如eq)和对应值 const [operator, value] = Object.entries(condition)[0]; expressions.push(`${expressionKey} ${operator} ${expressionValue}`); }); return expressions.length > 0 ? expressions.join(' AND ') : undefined; }
2. 修正ExpressionAttributeValues生成逻辑
遍历Filter时,要提取每个条件里的实际值(即condition.eq对应的值),再根据值的类型生成DynamoDB的类型对象:
const expressionNames: Record<string, string> = {}; const expValues: Record<string, any> = {}; const sets: string[] = []; for (const [k, condition] of Object.entries(filter)) { expressionNames[`#${k}`] = k; // 提取操作符和实际值 const [operator, value] = Object.entries(condition)[0]; sets.push(`#${k} ${operator} :${k}`); // 根据值类型生成DynamoDB格式 if (typeof value === 'number') { // DynamoDB的N类型要求值是字符串形式的数字 expValues[`:${k}`] = { N: value.toString() }; } else if (typeof value === 'string') { expValues[`:${k}`] = { S: value }; } // 可以根据需要扩展其他类型,比如布尔值{B: 'true'}等 }
正确生成的结果
经过修正后,针对你的Filter表达式{"Age":{"eq":3},"Sex":{"eq":"MALE"}},会生成:
- FilterExpression:
#Age eq :Age AND #Sex eq :Sex - ExpressionAttributeNames:
{"#Age":"Age","#Sex":"Sex"} - ExpressionAttributeValues:
{":Age": {"N": "3"}, ":Sex": {"S": "MALE"}}
这个结构符合DynamoDB的要求,不会再报错。
内容的提问来源于stack exchange,提问作者salt-pepper
相关产品推荐
相关产品推荐

