Для получения сведений о сотрудниках с помощью gsikey из dynamo db в AWS ServerLess

#node.js #amazon-s3 #aws-lambda #serverless #aws-serverless

#node.js #amazon-s3 #aws-lambda #без сервера #aws-бессерверный

Вопрос:

Я хочу повторно получить сведения о сотрудниках из DynamoDB с помощью ключа GSI. Здесь у меня есть таблица, в которой показана связь между сотрудником и отделами, я хотел бы получить сведения о сотруднике с помощью EmployeeID. Бессерверный шаблон, приведенный ниже

     service: dynaUser

custom:
  settings:
    POSTS_TABLE: Tbl-tblMasterDepartmentEmp1
provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1
  environment: ${self:custom.settings}
  
  iamRoleStatements:
   - Effect: "Allow"
     Action:
        - dynamodb:Query
        - dynamodb:DescribeTable
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
     Resource:
      - "arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.settings.POSTS_TABLE}"      
   - Effect: Allow
     Action:
        - dynamodb:Query
        - dynamodb:Scan
     Resource: 
      - "arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.settings.POSTS_TABLE}/index/*"
functions:
  createPost:
    handler: handler.createPost
    events:
    - http:
        path: /createEmployee
        method: post
        # integration: lambda
        # request:
        #   passThrough: NEVER
  createDepartment:
    handler: handler.createDepartmententry
    events:
    - http:
        path: /createDepartment
        method: post
        # integration: lambda
        # request:
        #   passThrough: NEVER        
  getEmpDataByID:
    handler: handler.getEmployeeDetails
    events:
    - http:
        path: /getemployee/{id}
        method: get
  getEmpDataByDeptID:
    handler: handler.getEmployeeDetailsByDeptId
    events:
    - http:
        method: get
        path: /getemployeeByDept
        integration: lambda
        request:
          template:
            application/json: '{ "deptId" : "$input.params(''deptId'')" }'  
resources:
  Resources:
    PostsTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
        - AttributeName: Pk_id
          AttributeType: "S"  
        - AttributeName: Sk_id
          AttributeType: "S"  
        - AttributeName: cat_type
          AttributeType: "S"  
        KeySchema:
        - AttributeName: "Pk_id"
          KeyType: "HASH"
        - AttributeName: "Sk_id"
          KeyType: "RANGE"
        TableName: ${self:custom.settings.POSTS_TABLE}
        GlobalSecondaryIndexes:
          - IndexName: empIdIndex
            KeySchema:
              - AttributeName: cat_type
                KeyType: HASH
              - AttributeName: Sk_id
                KeyType: RANGE
            Projection:
              ProjectionType: 'ALL'
        TimeToLiveSpecification:
          AttributeName: ttl
          Enabled: true
        BillingMode: PAY_PER_REQUEST
 

также используется запрос для получения данных о сотрудниках из базы данных и приведен ниже

// Получить сведения о сотрудниках с помощью Id

 module.exports.getEmployeeDetails = (event, context, callback) => {
  const id = event.pathParameters.id;
  const params = {
    Key: {
      Sk_id: id,
      type:"Stud"
    },
    TableName: deptTable,
    IndexName:"empIdIndex"
  };

  return db
    .get(params)
    .promise()
    .then((res) => {
      if (res.Item) callback(null, response(200, res.Item));
      else callback(null, response(404, { error: 'Post not found' }));
    })
    .catch((err) => callback(null, response(err.statusCode, err)));
};

  here I inclued error like

 {
    "message": "The provided key element does not match the schema",
    "code": "ValidationException",
    "time": "2020-12-09T17:27:24.439Z",
    "requestId": "E4QR1ITHPKNE7TQDS6S7R211O7VV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 22.385564476989238
}
 

Как я могу извлечь элемент из dynamodb без каких-либо ошибок, и я новичок в мире aws?

Ответ №1:

Проверьте сообщение об ошибке:

Недопустимое выражение KeyConditionExpression: имя атрибута является зарезервированным ключевым словом; зарезервированное ключевое слово: тип

DynamoDB сообщает вам, что вы KeyCondition используете зарезервированное ключевое слово called type . Полный список зарезервированных ключевых слов задокументирован здесь .

Теперь посмотрите на ваш KeyConditionExpression :

 'emp_id = :emp_id AND type = :type '
 

Примечание: в конце этого выражения также есть пробел.

У вас есть два варианта исправить это:

  1. Измените имя атрибута.
  2. Используется ExpressionAttributeNames для «переименования» атрибута в запросе.

Вариант 1 объясняется сам собой, вариант 2, вероятно, должен выглядеть следующим образом:

 const params = {
    KeyConditionExpression: 'emp_id = :emp_id AND #employeeType = :type',
    ExpressionAttributeNames: { 
        "#employeeType": "type" 
    },
    ExpressionAttributeValues: {
        ':emp_id': {'S': '1'},
        ':type':{'S':'Stud'}
    },
    TableName: deptTable,
    IndexName:"empIdIndex"   
};
 

Изменились две вещи:

  1. KeyConditionExpression Теперь вместо ключевого слова reserved используется имя атрибута «placeholder» #employeeType (по- # видимому, это обычное соглашение DynamoDB) type .
  2. Теперь существует «сопоставление» между именем заполнителя #employeeType и фактическим именем атрибута type в ExpressionAttributeNames .

Лично я бы рекомендовал не использовать зарезервированное ключевое слово в качестве имени атрибута (вариант 1).

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

1. @JintoJohn Глядя на определение вашей таблицы, у вас есть опечатка в именах атрибутов для вашего GSI. Ваш атрибут вызывается tpye , а не type используется, но вы используете type его в своем запросе. Таким образом, это может не сработать.

2. @JintoJohn Насколько я могу судить, у вас снова ошибка именования. Вы переименовали tpye в cat_type , но по-прежнему используете type в качестве имени ключа.