Dynamodb alexa 查询不调用数据项
Dynamodb alexa query not calling data item
我正在创建一项技能,我想调用 alexa 在特定日期和时间阅读不同的项目。
我目前的 table 设置如下:
日期|时间|状态
日期设置为主键,时间设置为排序键。我将日期和时间设置为 ASK 中的槽值,我可以看到这些值正在传递。我还确保我的日期和时间格式在 dynamodb 中是正确的。
我的问题是当我调用 alexa 并询问某个日期和时间的状态时,我无法让 alexa 以与该日期和时间对应的状态响应。
谁能帮我解决这个问题?或者告诉我哪里出错了,我会在下面插入我的代码。
const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();
var AWSregion = 'us-east-1'; // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
region: "'us-east-1'"
});
let GetMachineStateIntent = (context, callback, dateSlot, timeSlot) => {
var params = {
TableName: "updatedincident",
KeyConditionExpression: 'date = :dVal and time < :tVal',
ExpressionAttributeValues: {
':dVal': dateSlot,
':tVal': timeSlot
},
ScanIndexForward: false // gets values in reverse order by time
};
dbClient.query(params, function (err, data) {
if (err) {
// failed to read from table for some reason..
console.log('failed to load data item:\n' + JSON.stringify(err, null, 2));
// let skill tell the user that it couldn't find the data
sendResponse(context, callback, {
output: "the data could not be loaded from your database",
endSession: false
});
} else {
let dataItem = data.Items[0];
console.log('loaded data item:\n' + JSON.stringify(dataItem, null, 2));
// assuming the item has an attribute called "state"..
sendResponse(context, callback, {
output: dataItem.state,
endSession: false
});
}
});
};
function sendResponse(context, callback, responseOptions) {
if(typeof callback === 'undefined') {
context.succeed(buildResponse(responseOptions));
} else {
callback(null, buildResponse(responseOptions));
}
}
function buildResponse(options) {
var alexaResponse = {
version: "1.0",
response: {
outputSpeech: {
"type": "SSML",
"ssml": `<speak><prosody rate="slow">${options.output}</prosody></speak>`
},
shouldEndSession: options.endSession
}
};
if (options.repromptText) {
alexaResponse.response.reprompt = {
outputSpeech: {
"type": "SSML",
"ssml": `<speak><prosody rate="slow">${options.reprompt}</prosody></speak>`
}
};
}
return alexaResponse;
}
exports.handler = (event, context, callback) => {
try {
var request = event.request;
if (request.type === "LaunchRequest") {
sendResponse(context, callback, {
output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
endSession: false
});
} else if (request.type === "IntentRequest") {
if (request.intent.name === "GetMachineStateIntent") {
var dateSlot = request.intent.slots.Date != null
? request.intent.slots.Date. value : null;
var timeSlot = request.intent.slots.Time != null
? request.intent.slots.Time.value : null;
// pass the slot values to the GetMachineStateIntent function
GetMachineStateIntent(context, callback, dateSlot, timeSlot);
} else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
sendResponse(context, callback, {
output: "ok. good bye!",
endSession: true
});
}
else if (request.intent.name === "AMAZON.HelpIntent") {
sendResponse(context, callback, {
output: "you can ask me about incidents that have happened or states of machines in the past",
reprompt: "what can I help you with?",
endSession: false
});
}
else {
sendResponse(context, callback, {
output: "I don't know that one! please try again!",
endSession: false
});
}
}
else if (request.type === "SessionEndedRequest") {
sendResponse(context, callback, ""); // no response needed
}
else {
// an unexpected request type received.. just say I don't know..
sendResponse(context, callback, {
output: "I don't know that one! please try again!",
endSession: false
});
}
} catch (e) {
// handle the error by logging it and sending back an failure
console.log('Unexpected error occurred in the skill handler!', e);
if(typeof callback === 'undefined') {
context.fail("Unexpected error");
} else {
callback("Unexpected error");
}
}
};
我目前使用上述代码得到的响应是
'the data could not be loaded from your database'
云表也告诉我这个
2018-05-16T09:29:06.635Z 93d4b6e6-58eb-11e8-b686-597d65771e90 failed to load data item:
{
"message": "Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: date",
"code": "ValidationException",
"time": "2018-05-16T09:29:06.633Z",
"requestId": "EQPQTAGO4QKH9SM5GSOA9O3DDFVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 35.56027710686527
}
在 GetMachineStateIntent
函数中,尝试像这样更改 params
结构:
var params = {
TableName: "updatedincident",
KeyConditionExpression: '#d = :dVal and #t < :tVal',
ExpressionAttributeValues: {
':dVal': dateSlot,
':tVal': timeSlot
},
ExpressionAttributeNames: {
'#d': 'date',
'#t': 'time'
},
ScanIndexForward: false // gets values in reverse order by time
};
看起来 date
这个词是保留关键字,所以它不能直接用在 date = :dVal
这样的表达式中,这就是为什么你必须给它一个属性名别名 (#d
) 映射回实际的属性名称 (date
).
在 DynamoDB 中,您必须使用两个键,即主键和主排序键。查询根据这两个键搜索请求的值。
试试我的代码:
'FindName': function() {
var tableName = "CVRaman";
var userName = "Prateek";
var userId = "kapoor";
const dynamodbParams = {
TableName: tableName,
Key: {
userId: userId,
userName: userName,
},
ProjectionExpression: 'userName', //Projection Expression is used to select only specific columns which we want to get
};
console.log("Attempting to find name", dynamodbParams);
dynamoDb.get(dynamodbParams).promise()
.then(data => {
console.log('name found', dynamodbParams);
console.log(data.Item.userName);
var a = data.Item.userName;
console.log(a);
this.emit(':ask', 'Name as ' + a);
})
.catch(err => {
console.log(err);
this.emit(':tell', 'we have a problem');
});
},
我正在创建一项技能,我想调用 alexa 在特定日期和时间阅读不同的项目。 我目前的 table 设置如下: 日期|时间|状态
日期设置为主键,时间设置为排序键。我将日期和时间设置为 ASK 中的槽值,我可以看到这些值正在传递。我还确保我的日期和时间格式在 dynamodb 中是正确的。
我的问题是当我调用 alexa 并询问某个日期和时间的状态时,我无法让 alexa 以与该日期和时间对应的状态响应。
谁能帮我解决这个问题?或者告诉我哪里出错了,我会在下面插入我的代码。
const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();
var AWSregion = 'us-east-1'; // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
region: "'us-east-1'"
});
let GetMachineStateIntent = (context, callback, dateSlot, timeSlot) => {
var params = {
TableName: "updatedincident",
KeyConditionExpression: 'date = :dVal and time < :tVal',
ExpressionAttributeValues: {
':dVal': dateSlot,
':tVal': timeSlot
},
ScanIndexForward: false // gets values in reverse order by time
};
dbClient.query(params, function (err, data) {
if (err) {
// failed to read from table for some reason..
console.log('failed to load data item:\n' + JSON.stringify(err, null, 2));
// let skill tell the user that it couldn't find the data
sendResponse(context, callback, {
output: "the data could not be loaded from your database",
endSession: false
});
} else {
let dataItem = data.Items[0];
console.log('loaded data item:\n' + JSON.stringify(dataItem, null, 2));
// assuming the item has an attribute called "state"..
sendResponse(context, callback, {
output: dataItem.state,
endSession: false
});
}
});
};
function sendResponse(context, callback, responseOptions) {
if(typeof callback === 'undefined') {
context.succeed(buildResponse(responseOptions));
} else {
callback(null, buildResponse(responseOptions));
}
}
function buildResponse(options) {
var alexaResponse = {
version: "1.0",
response: {
outputSpeech: {
"type": "SSML",
"ssml": `<speak><prosody rate="slow">${options.output}</prosody></speak>`
},
shouldEndSession: options.endSession
}
};
if (options.repromptText) {
alexaResponse.response.reprompt = {
outputSpeech: {
"type": "SSML",
"ssml": `<speak><prosody rate="slow">${options.reprompt}</prosody></speak>`
}
};
}
return alexaResponse;
}
exports.handler = (event, context, callback) => {
try {
var request = event.request;
if (request.type === "LaunchRequest") {
sendResponse(context, callback, {
output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
endSession: false
});
} else if (request.type === "IntentRequest") {
if (request.intent.name === "GetMachineStateIntent") {
var dateSlot = request.intent.slots.Date != null
? request.intent.slots.Date. value : null;
var timeSlot = request.intent.slots.Time != null
? request.intent.slots.Time.value : null;
// pass the slot values to the GetMachineStateIntent function
GetMachineStateIntent(context, callback, dateSlot, timeSlot);
} else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
sendResponse(context, callback, {
output: "ok. good bye!",
endSession: true
});
}
else if (request.intent.name === "AMAZON.HelpIntent") {
sendResponse(context, callback, {
output: "you can ask me about incidents that have happened or states of machines in the past",
reprompt: "what can I help you with?",
endSession: false
});
}
else {
sendResponse(context, callback, {
output: "I don't know that one! please try again!",
endSession: false
});
}
}
else if (request.type === "SessionEndedRequest") {
sendResponse(context, callback, ""); // no response needed
}
else {
// an unexpected request type received.. just say I don't know..
sendResponse(context, callback, {
output: "I don't know that one! please try again!",
endSession: false
});
}
} catch (e) {
// handle the error by logging it and sending back an failure
console.log('Unexpected error occurred in the skill handler!', e);
if(typeof callback === 'undefined') {
context.fail("Unexpected error");
} else {
callback("Unexpected error");
}
}
};
我目前使用上述代码得到的响应是
'the data could not be loaded from your database'
云表也告诉我这个
2018-05-16T09:29:06.635Z 93d4b6e6-58eb-11e8-b686-597d65771e90 failed to load data item:
{
"message": "Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: date",
"code": "ValidationException",
"time": "2018-05-16T09:29:06.633Z",
"requestId": "EQPQTAGO4QKH9SM5GSOA9O3DDFVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 35.56027710686527
}
在 GetMachineStateIntent
函数中,尝试像这样更改 params
结构:
var params = {
TableName: "updatedincident",
KeyConditionExpression: '#d = :dVal and #t < :tVal',
ExpressionAttributeValues: {
':dVal': dateSlot,
':tVal': timeSlot
},
ExpressionAttributeNames: {
'#d': 'date',
'#t': 'time'
},
ScanIndexForward: false // gets values in reverse order by time
};
看起来 date
这个词是保留关键字,所以它不能直接用在 date = :dVal
这样的表达式中,这就是为什么你必须给它一个属性名别名 (#d
) 映射回实际的属性名称 (date
).
在 DynamoDB 中,您必须使用两个键,即主键和主排序键。查询根据这两个键搜索请求的值。
试试我的代码:
'FindName': function() {
var tableName = "CVRaman";
var userName = "Prateek";
var userId = "kapoor";
const dynamodbParams = {
TableName: tableName,
Key: {
userId: userId,
userName: userName,
},
ProjectionExpression: 'userName', //Projection Expression is used to select only specific columns which we want to get
};
console.log("Attempting to find name", dynamodbParams);
dynamoDb.get(dynamodbParams).promise()
.then(data => {
console.log('name found', dynamodbParams);
console.log(data.Item.userName);
var a = data.Item.userName;
console.log(a);
this.emit(':ask', 'Name as ' + a);
})
.catch(err => {
console.log(err);
this.emit(':tell', 'we have a problem');
});
},