Как указать параметры для DynamoDB PartiQL в Nodejs

#javascript #node.js #amazon-dynamodb #aws-sdk-nodejs #partiql

Вопрос:

Я хочу выполнить запрос SELECT на DynamoDB с помощью PartiQL в NodeJS и получить ошибки.

простое утверждение работает без проблем.

     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']
          ]
      })
    )
 

Комментарии:

1. У меня нет возможности проверить это для вас, но разве переданные вами параметры не должны быть заключены в двойные кавычки? Создается впечатление, что вы пытаетесь передать вложенный объект массива в то, что должно быть массивом, состоящим только из одного элемента, переданного в виде строки. Не уверен, что я прав, поэтому я опубликовал это в качестве комментария, а не ответа. Надеюсь, это поможет.

Ответ №1:

Насколько я могу судить, не совсем возможно сделать то, что вы пытаетесь сделать (передать массив строк в качестве параметра в подготовленном операторе в качестве правого аргумента оператору IN 😅).

Кажется, лучшее, что вы можете сделать, это:

 executeStatement({
  Statement: `SELECT * FROM Users WHERE userId in [?, ?]`,
  Parameters: [
    {"S": "firstId"},
    {"S": "secondId"}, 
    // ...etc.
  ]
})
 

Обратите внимание, что Parameters свойство принимает массив пар ключ-значение. Каждое значение атрибута параметра описывается как пара имя-значение. Имя-это тип данных (например "S" , для строки), а значение-это сами данные (например, идентификатор пользователя).

В вашем случае, если бы у вас был список пользователей, вы могли бы сделать что-то вроде:

 
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}))  
})
 

Имейте в виду, что, вероятно, существует какой-то верхний предел количества параметров, которые вы можете передать, но я нигде не смог найти это число, задокументированное.

Ответ №2:

 // Before
SELECT * FROM Users WHERE userId in ?

// After
SELECT * FROM Users WHERE userId in '?'
 

Комментарии:

1. Пожалуйста, подробнее об этом, предоставьте ссылку на документацию, чтобы кто-то мог извлечь уроки из вашего ответа.

2. docs.aws.amazon.com/amazondynamodb/latest/developerguide/…

3. @Picard Я нашел подсказку в официальной документации. Насколько я знаю, нет ни одной части, которая была бы объяснена напрямую