#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 '
Примечание: в конце этого выражения также есть пробел.
У вас есть два варианта исправить это:
- Измените имя атрибута.
- Используется
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"
};
Изменились две вещи:
KeyConditionExpression
Теперь вместо ключевого слова reserved используется имя атрибута «placeholder»#employeeType
(по-#
видимому, это обычное соглашение DynamoDB)type
.- Теперь существует «сопоставление» между именем заполнителя
#employeeType
и фактическим именем атрибутаtype
вExpressionAttributeNames
.
Лично я бы рекомендовал не использовать зарезервированное ключевое слово в качестве имени атрибута (вариант 1).
Комментарии:
1. @JintoJohn Глядя на определение вашей таблицы, у вас есть опечатка в именах атрибутов для вашего GSI. Ваш атрибут вызывается
tpye
, а неtype
используется, но вы используетеtype
его в своем запросе. Таким образом, это может не сработать.2. @JintoJohn Насколько я могу судить, у вас снова ошибка именования. Вы переименовали
tpye
вcat_type
, но по-прежнему используетеtype
в качестве имени ключа.