Как удалить элементы Amazon DynamoDB с помощью LocalSeondaryIndex? - PullRequest
0 голосов
/ 19 июня 2020

Я определил свою DynamoDB, как показано ниже в сценарии облачной информации:

TodosDynamoDBTable:
  Type: AWS::DynamoDB::Table
  Properties:
    AttributeDefinitions:
      - AttributeName: userId
        AttributeType: S           
      - AttributeName: createdAt
        AttributeType: S                                     
      - AttributeName: todoId
        AttributeType: S                                               
    KeySchema:
      - AttributeName: userId
        KeyType: HASH   
      - AttributeName: createdAt
        KeyType: RANGE                                   
    BillingMode: PAY_PER_REQUEST
    TableName: ${self:provider.environment.TODOS_TABLE}
    LocalSecondaryIndexes:
      - IndexName: ${self:provider.environment.TODOID_INDEX}
        KeySchema:
          - AttributeName: userId
            KeyType: HASH        
          - AttributeName: todoId
            KeyType: RANGE               
        Projection:
          ProjectionType: ALL # What attributes will be copied to an index

Теперь я хочу найти элемент на основе userId и todoId. Итак, я использовал приведенный ниже машинописный код:

  const key = {
    userId: userId,
    todoId: todoId
  }

  await docClient.delete({
      TableName: todosTable,
      Key: key
  }).promise();

Но это дает мне ошибку от CloudWatch

2020-06-19T18:03:17.349Z    00a89359-428f-4a7d-b63c-500e7d062c1b    ERROR   Invoke Error    
{
    "errorType": "ValidationException",
    "errorMessage": "The provided key element does not match the schema",
    "code": "ValidationException",
    "message": "The provided key element does not match the schema",
    "time": "2020-06-19T18:03:17.347Z",
    "requestId": "7EJTPMFQKEUTQAKNI1UVQ0FRF7VV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 6.9291082443874386,
    "stack": [
        "ValidationException: The provided key element does not match the schema",
        "    at constructor.httpResponse (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/protocol/json.js:47:1)",
        "    at constructor.shift [as callListeners] (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/sequential_executor.js:100:1)",
        "    at constructor.doneCallback [as emit] (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/sequential_executor.js:75:1)",
        "    at constructor.call [as emitEvent] (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/request.js:683:1)",
        "    at constructor.emit (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/request.js:22:1)",
        "    at r.call [as runTo] (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/state_machine.js:14:1)",
        "    at runTo (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/state_machine.js:26:1)",
        "    at constructor.done (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/request.js:38:1)",
        "    at constructor.call (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/request.js:685:1)",
        "    at constructor.Error [as callListeners] (/var/task/src/lambda/http/webpack:/node_modules/aws-sdk/lib/sequential_executor.js:108:1)"
    ]
}

Каков правильный синтаксис для удаления на основе userId и / или todoId?

ОБНОВЛЕНИЕ: docClient создается из стандартного шаблона aws XRay и DynamoDB

const XAWS = AWSXRay.captureAWS(AWS)
const docClient = new XAWS.DynamoDB.DocumentClient()

Я также могу запросить, используя

  const result = await docClient.query({
    TableName: todosTable,
    IndexName: todoIdIndex,
    KeyConditionExpression: 'userId = :userId and todoId = :todoId',
    ExpressionAttributeValues: {
      ':userId': userId,
      ':todoId': todoId
    }
  }).promise()

1 Ответ

1 голос
/ 19 июня 2020

Не уверен, что это с клиентом документов, но это должно быть то, что вам нужно. Обычно сначала запрос, а затем удаление. Это потому, что ваша таблица проиндексирована с помощью userId и createdAt, поэтому вам нужно выяснить их, прежде чем вы сможете удалить запись

const result = await docClient.query({
    TableName: todosTable,
    IndexName: todoIdIndex,
    KeyConditionExpression: 'userId = :userId and todoId = :todoId',
    ExpressionAttributeValues: {
      ':userId': userId,
      ':todoId': todoId
    },
    ProjectionExpression: 'userId, createdAt'
  }).promise()

if (result.$response.data && result.$response.data.Items) {
    const key = {
        userId: result.$response.data.Items[0]['userId'],
        createdAt: result.$response.data.Items[0]['createdAt']
    }
    await docClient.delete({
        TableName: todosTable,
        Key: key
    }).promise()
}
...