我想在 NodeJs 中使用 PartiQL 在 DynamoDb 上执行 SELECT 查询,但出现错误。
简单的语句没有问题。
const r = await client.send(
new ExecuteStatementCommand({
Statement: `SELECT * FROM Users WHERE userId in ['abcd1234']`
})
)
但是当尝试执行带有参数的语句时,我收到了错误。
代码
const r2 = await client.send(
new ExecuteStatementCommand({
Statement: `SELECT * FROM Users WHERE userId in ?`,
Parameters: [
['abcd1234']
]
})
)
错误
{
"errorType": "ValidationException",
"errorMessage": "1 validation error detected: Value '[]' at 'parameters' failed to satisfy constraint: Member must have length greater than or equal to 1",
"trace": [
"ValidationException: 1 validation error detected: Value '[]' at 'parameters' failed to satisfy constraint: Member must have length greater than or equal to 1",
" at deserializeAws_json1_0ExecuteStatementCommandError (/var/task/node_modules/@aws-sdk/client-dynamodb/dist/cjs/protocols/Aws_json1_0.js:2202:41)",
" at processTicksAndRejections (internal/process/task_queues.js:97:5)",
" at async /var/task/node_modules/@aws-sdk/middleware-serde/dist/cjs/deserializerMiddleware.js:6:20",
" at async /var/task/node_modules/@aws-sdk/middleware-signing/dist/cjs/middleware.js:12:24",
" at async StandardRetryStrategy.retry (/var/task/node_modules/@aws-sdk/middleware-retry/dist/cjs/defaultStrategy.js:56:46)",
" at async /var/task/node_modules/@aws-sdk/middleware-logger/dist/cjs/loggerMiddleware.js:6:22",
" at async /var/task/node_modules/@aws-sdk/lib-dynamodb/dist/cjs/commands/ExecuteStatementCommand.js:29:26",
" at async Runtime.handler (/var/task/save.js:39:16)"
]
}
有没有人有解决办法?
这是完整代码。
const client = DynamoDBDocumentClient.from(
new DynamoDBClient({})
);
// this works
const r = await client.send(
new ExecuteStatementCommand({
Statement: `SELECT * FROM Users WHERE userId in ['abcd1234']`
})
)
// this gets an error
const r2 = await client.send(
new ExecuteStatementCommand({
Statement: `SELECT * FROM Users WHERE userId in ?`,
Parameters: [
['abcd1234']
]
})
)
据我所知,不太可能做你想做的事情(将一个字符串数组作为准备好的语句中的参数传递给 IN 运算符的右侧参数😅)。
看来你能做的最好的就是:
executeStatement({
Statement: `SELECT * FROM Users WHERE userId in [?, ?]`,
Parameters: [
{"S": "firstId"},
{"S": "secondId"},
// ...etc.
]
})
请注意,
Parameters
属性采用键值对数组。每个参数属性值都被描述为名称-值对。名称是数据类型(例如 "S"
表示字符串),值是数据本身(例如用户 ID。)
就您而言,如果您有用户列表,您可以执行以下操作:
const users = [
{ id: "id-1" },
{ id: "id-2" },
{ id: "id-3" },
]
executeStatement({
Statement: `SELECT * FROM Users WHERE userId in [${users.map(() => '?').join(',')}]`,
Parameters:
users.map(user => ({"S": user.id}))
})
请注意,您可以传递的参数数量可能有一些上限,但我在任何地方都找不到这个数字的记录。
// Before
SELECT * FROM Users WHERE userId in ?
// After
SELECT * FROM Users WHERE userId in '?'
当我在 Python 中使用 boto3 客户端尝试此操作时,它对我有用的方式是直接传递参数值,而不是它们在文档中显示的类型/值映射
executeStatement({
Statement: `SELECT * FROM Users WHERE userId in (?,?,?)`,
Parameters: [
'id-1',
'id-2',
'id-3'
]
})
当我通过
[{"S": "id-1"}, {"S": "id-2"}, {"S": "id-3"}]
我得到
An error occurred (ValidationException) when calling the ExecuteStatement operation: Key value must be of type S, N, or B. Key name: accessionNumber, Key type: M