使用Alexa查询调用DynamoDB

时间:2018-03-01 13:18:46

标签: amazon-web-services aws-lambda amazon-dynamodb alexa alexa-skills-kit

我尝试使用Alexa创建一项技能,使用扫描或查询功能(或两者)从DynamoDB表中读取数据。

我表格中的列是日期,时间和电影名称。

我是新手,但我设法将我的Lambda功能链接到Alexa。我还创建了一个单独的Lambda函数,当我配置测试事件时,它将从我的表中调用数据,因此当我输入特定日期时,它将调用相应的电影和时间。但是现在我想把它实现到Alexa中并且不确定如何。

这是我目前的代码



console.log('Loading function');

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dclient = new AWS.DynamoDB.DocumentClient();

var getItems = (event, context, callback)=>{
    
    dclient.get(event.params,(error,data)=>{
        if(error){
            callback(null,"error occurerd");
        }
        else{
            callback(null,data);
        }
    });
};

exports.handler = getItems;

exports.handler = (event, context, callback) => {
    try {

        var request = event.request;

        if (request.type === "LaunchRequest") {
            context.succeed(buildResponse({
                speechText: "Welcome to H.S.S.M.I skill, what would you like to find",
                repromptText: "I repeat, Welcome to my skill, what would you like to find",
                endSession: false
            }));
        }
        else if (request.type === "IntentRequest") {
            let options = {};         


            if (request.intent.name === "cinema") {
            } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
                options.speechText = "ok, good bye.";
                options.endSession = true;
                context.succeed(buildResponse(options));
            }
             else if (request.intent.name === "AMAZON.HelpIntent") {
                options.speechText = "My skill will read your table depending on what is asked. For example, you can ask what about a specific date. Please refer to skill description for all possible utterences.";
                options.repromptText = "What is the data sign you want to know  about today? If you want to exit from my  skill please say stop or cancel.";
                options.endSession = false;
                context.succeed(buildResponse(options));
            }
            else {
                context.fail("Unknown Intent");
            }
        }

        else if (request.type === "SessionEndedRequest") {
            options.endSession = true;
            context.succeed();
        }
        else {
            context.fail("Unknown Intent type");
        }




    } catch (e) {

    }


};

function buildResponse(options) {
    var response = {
        version: "1.0",
        response: {
            outputSpeech: {
                "type": "SSML",
                "ssml": `<speak><prosody rate="slow">${options.speechText}</prosody></speak>`
            },

            shouldEndSession: options.endSession
        }
    };

    if (options.repromptText) {
        response.response.reprompt = {
            outputSpeech: {
                "type": "SSML",
                "ssml": `<speak><prosody rate="slow">${options.repromptText}</prosody></speak>`
            }
        };
    }

    return response;
}

function readDynamoItem(params, callback) {
    
    var AWS = require('aws-sdk');
    AWS.config.update({region: AWSregion});
    var dynamodb = new AWS.DynamoDB();
    console.log('reading item from DynamoDB table');

    dynamodb.scan(params, function(err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else{
            console.log(data); // successful response
            callback(JSON.stringify(data));
        }
    });
    var docClient = new AWS.DynamoDB.DocumentClient();
    //Get item by key
    docClient.get(params, (err, data) => {
        if (err) {
            console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
        } else {
            console.log("GetItem succeeded:", JSON.stringify(data, null, 2));

            callback(data.Item.message);  // this particular row has an attribute called message

        }
    });

}

///////////////////////////////////////////////////////////////////////////////
&#13;
&#13;
&#13;

这是我的DBHandler

&#13;
&#13;
var AWS = require('aws-sdk');
AWS.config.update({
    region: "'us-east-1'"
});

let docClient = new AWS.DynamoDB.DocumentClient();

var table = "Cinema";

let getItems = (Id,callback) => {   
  
    var params = {
        TableName: "cinema",
        Key: {
            "date": "2018-01-04",
            "filmname": "rugrats"
        }
    };

    docClient.get(params, function (err, data) {
        callback(err, data);
    });

};
module.exports = {
    getItems
};
&#13;
&#13;
&#13;

我可以启动应用程序,并且我有一个Lambda函数,当我配置测试事件以从某个日期查找电影时,它可以独立工作,但我不能让它与Alexa一起工作。

任何人都可以帮助我或指明我出错的地方

UPDATE *************

以下是我的意图架构的设置方式

&#13;
&#13;
{
  "intents": [
    {
      "slots": [
        {
          "name": "sincedate",
          "type": "AMAZON.DATE"
        }
      ],
      "intent": "date"
    },
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "slots": [
        {
          "name": "sincedate",
          "type": "AMAZON.DATE"
        }
      ],
      "intent": "cinema"
    },
    {
      "intent": "MyIntent"
    }
  ]
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

第1部分 - 权限

您可能无法从技能中读取DynamoDB的一个可能原因是权限。

您应该仔细检查分配给技能lambda的IAM角色,以确保它具有从DynamoDB读取的权限。

一些参考文献:

第2部分 - 实际的技能处理程序Lambda

我重新阅读了您的问题,我对您谈论设置第二个Lambda以从Dynamo读取数据的部分感到困惑。你不应该有两个Lambda函数 - 只有一个处理来自Alexa的请求,并且在调用Dynamo之后你应该将你的响应返回给Alexa。

现在,具体细节。在您的第一个代码段中,您有:

exports.handler = getItems;

exports.handler = (event, context, callback) => {
    // here you have your handler to handle alexa responses 
}

立即突出的一点是,您首先将处理程序设置为getItems,然后重置回应该响应Alexa的处理程序。

我猜测的另一件事是,有时技能会起作用,就像你第一次启动时一样,可能是你说帮助,但在其他情况下它并不是,就像你发送时一样它是电影&#34;意图。

这是因为从Alexa请求到您的技能的入口点是exports.handler,它基本上被定义为具有三个参数的函数(它像void main(int argc,char * argv)交流计划的[])。

第一个参数 - event是您技能的输入。 Alexa将在此处提供信息,例如请求类型,是否为意图,意图名称,会话信息等。

第二个和第三个参数 - contextcallback是用于从lambda函数返回控制的内容,具体取决于节点运行时。对于Note v4和更新版本,您使用回调,对于旧版本,您使用上下文。

您可以使用类似的内容发回成功回复:

if(typeof callback === 'undefined') {
     context.succeed("successful response message");
} else {
     callback(null, "successful response message");
}

这样的事情发送失败的回复

if(typeof callback === 'undefined') {
     context.fail("failure response message");
} else {
     callback("failure response message", null);
}

总而言之,这里是一个基本的Lambda处理程序,它始终响应您的技能调用:

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. what do you want to find?",
        endSession: false
      });
    }
    else if (request.type === "IntentRequest") {
      let options = {};         
      if (request.intent.name === "cinema") {
        // this is where we will wire up the dynamo call
        // for now, just send a simple response and end the session
        sendResponse(context, callback, {
          output: "cinema not implemented yet!",
          endSession: true
        });
      } 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 films",
          reprompt: "what can I help you with?"
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! Good bye!",
          endSession: true
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // un unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! Good bye!",
          endSession: true
      });
    }
  } 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");
    }
  }
};

达到这一点,技能应该是有效的,它应该能够处理您的所有请求。假设您已正确配置了交互模型并且cinema意图已发送给您的技能,那么您可以使用发电机客户端来响应表中的数据。

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();

let handleCinemaIntent = (context, callback) => {    
  let params = {
    TableName: "cinema",
    Key: {
        "date": "2018-01-04",
        "filmname": "rugrats"
    }
  };
  dbClient.get(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 Dynamo",
          endSession: true
       });
    } else {
       console.log('loaded data item:\n' + JSON.stringify(data.Item, null, 2))
       // assuming the item has an attribute called "message"..
       sendResponse(context, callback, {
          output: data.Item.message,
          endSession: true
       });
    }
  });
};


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. what do you want to find?",
        endSession: false
      });
    }
    else if (request.type === "IntentRequest") {
      let options = {};         
      if (request.intent.name === "cinema") {
        handleCinemaIntent(context, callback);
      } 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 films",
          reprompt: "what can I help you with?"
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! Good bye!",
          endSession: true
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // un unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! Good bye!",
          endSession: true
      });
    }
  } 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");
    }
  }
};