简体   繁体   中英

Dynamodb alexa query not calling data item

I am creating a skill where I want to call alexa to read differnt items at certain dates and times. I currently have my table set up as follows: Date|Time|State

Date is setup as my primary key with time as my sort key. I have setup date and time as slot values in ASK, and I can see that these values are being passed through. I have also made sure the format of my date and time is correct within dynamodb.

My issue is when I call alexa and ask for the state at a certain date and time, I can't get alexa to respond with the state corresponding with that date and time.

Can anyone help me with this? Or tell me where i'm going wrong, I will insert my code below.

 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 response i currently get with my above code is

'the data could not be loaded from your database'

Cloud watch also tells me this

 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 } 

In the GetMachineStateIntent function, try changing the params structure like this:

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 
};

It looks like the word date is a reserved keyword so it can't be used directly in an expression such as date = :dVal which is why you must give it an attribute name alias ( #d ) which maps back to the actual attribute name ( date ).

In DynamoDB, you have to use two keys ie Primary key and Primary sort key. The query searches on the basis of these two keys for the requested value.

Try my code:

'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');
        });
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM