I want to retieve Employee details from dynamoDb using GSI Key. Here I have a table which depicts a relation between employee and departments, I would like to get an employee details by using employeeId. Serverless Template Given below
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
also used query to retrieve employee Data from Db and Given below
// Get employee Details by using 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
}
How can I retrieve item from dynamodb with out any error ,and I am new to the aws world?
Check the error message:
Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: type
DynamoDB is telling you that your KeyCondition
uses a reserved keyword called type
. The full list of reserved keywords is documented here.
Now look at your KeyConditionExpression
:
'emp_id = :emp_id AND type = :type '
Note: There is also whitespace at the end of this expression.
You have two options to fix this:
ExpressionAttributeNames
to "rename" the attribute in the query.Option 1 is self explaining, option 2 should probably look like this:
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"
};
Two things changed:
KeyConditionExpression
now uses a "placeholder" attribute name called #employeeType
(the #
appears to be a common DynamoDB convention) instead of the reserved keyword type
.#employeeType
and the actual attribute name type
in ExpressionAttributeNames
.Personally, I'd recommend not using a reserved keyword as attribute name (option 1).