从实时数据库获取JSON数据到Dialogflow内联编辑器(Google助手) [英] get json data from realtime database to Dialogflow inline editor (google assistant)

查看:109
本文介绍了从实时数据库获取JSON数据到Dialogflow内联编辑器(Google助手)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是编程的入门者,我正在从事与Google Assistant相关的项目的业余时间,这是我第一次使用Firebase Realtime数据库,却不知道如何从那里获取数据,下面的代码在Dialogflow的内联编辑器中,其中的1、2和3类是有学分的学生。我进行了一些更改,并将这三个类别(类别1 2和3)放在下面的数据库图片中,我想从代码中删除这三个类别并将其替换为实时数据库中的类别。



因为这是我第一次使用该数据库,所以我不知道如何使用nodejs从那里获取数据。



 函数categoryac(agent){const classes = {category1:{ Alex:25, Jennifer:45, Justin:35, Peter: 89},类别2:{ Alex:95, Jennifer:75, Justin:85, Peter:59},category3:{ Alex:67, Jennifer:55, Justin: 45, Peter:15},}; const categoried = agent.parameters [ categoried]; const categoryAmount = agent.parameters [ categoryAmount]; const category = category [categoried]; const聚合= category [categoryAmount]; agent.add(`$ {categoried}的$ {categoryAmount}是$ {aggregate}`); }让intentMap = new Map(); intentMap.set('category',categoryac); agent.handleRequest(intentMap); });  





更新
我使用下面的代码,如下所示:



 函数categoryac(agent){const categoried = agent.parameters [ categoried]; const categoryAmount = agent.parameters [ categoryAmount]; var admin = require('firebase-admin'); admin.initializeApp({凭证:admin.credential.cert({projectId:'',clientEmail:'',privateKey:''}),dblink:'www。*****。*****。com' }); var something = admin.database(); var related = something.ref(`category / $ {categoried} / $ {categoryAmount}`);返回related.once( value).then(快照=> {var聚合=快照.value(); agent.add(`$ {categoried}的$ {categoryAmount}是$ {aggregate}`);} ).catch(fail => {agent.add('呃,出了点问题。'); console.error(fail);}); }让intentMap = new Map(); intentMap.set('category',categoryac); agent.handleRequest(intentMap);});  


收到错误消息:'MalformedResponse
无法解析Dialogflow日志错误:



  { insertId: v ***** 2标签:{频道:预览查询流: GOOGLE_USER源: JSON_RESPONSE_VALIDATION}日志名称: projects / **** / logs / actions.googleapis.com%2Factions receiveTimestamp: 2019-01-07T14:45:29.274840871Z资源:{标签:{action_id: actions.intent.TEXT project_id: ****** version_id:}类型: assistant_action}严重性: ERROR textPayload: MalformedResponse:由于语音响应为空,无法将Dialogflow响应解析为AppResponse时间戳: 2019-01-07T14:45:29.26 6062732Z跟踪: projects / 383182941858 / traces / ABwppHFK_PehMj1XEs_Arng9VL7_zShy-EWvoziK0Ro6v74TaduNG1cJaRMnGAZMoLZhtILdG2hEBkDvJQ}  

以下是日志中的错误:

 错误:默认的Firebase应用程序已存在。这意味着您多次调用了initializeApp(),而没有提供应用名称作为第二个参数。在大多数情况下,您只需要调用一次initializeApp()。但是,如果您确实要初始化多个应用程序,则将第二个参数传递给initializeApp()以为每个应用程序指定唯一的名称。 
在FirebaseAppError.Error(本机)
在FirebaseAppError.FirebaseError [作为构造函数](/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28)
在FirebaseAppError.PrefixedFirebaseError [作为构造函数](/user_code/node_modules/firebase-admin/lib/utils/error.js:85:28)
在新的FirebaseAppError(/ user_code / node_modules / firebase-admin / lib / utils / error.js:119:28)FirebaseNamespaceInternals.initializeApp(/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:68:23)
在FirebaseNamespace.initializeApp(/ user_code / node_modules / firebase-admin / lib / firebase-namespace.js:362:30)
在categoryac(/user_code/index.js:34:11)
在WebhookClient.handleRequest(/ user_code / node_modules / dialogflow-fulfillment / src / dialogflow-fulfillment.js:303:44)
在export.dialogflowFirebaseFulfillment.functions.https.onRequest(/user_code/index.js:91:9)在cloudFunction的
(/ user_code / node_modules / firebase-functions / lib / providers / https.js:57:9)


解决方案

您需要学习一些内容。



第一个方法是添加Firebase Admin SDK 到您的项目。



您还需要学习如何使用该库检索数据。 Firebase使用基于引用路径的方法来获取数据,因此您需要确保正确构建路径。



最后,因为您是在a履行处理程序,并且您正在进行异步调用,则需要确保您返回了Promise。幸运的是,获取数据还涉及返回一个Promise,因此您可以返回此Promise。



代码的一部分可能看起来像这样(未经测试):

 函数personFacts(agent){
const personId = agent.parameters [ personId];
const personMeasurement = agent.parameters [ personMeasurement];

var db = admin.database();
var ref = db.ref(`person / $ {personId} / $ {personMeasurement}`);
return ref.once( value)
.then(snapshot => {
var result = snapshot.val();
agent.add(`$ {personId }的$ {personMeasurement}是$ {result}`);
})
.catch(err => {
agent.add('哦,出事了。' );
console.error(err);
});

}

如您所述,您需要初始化Firebase管理库使用一个密钥,该密钥将使您可以通过服务帐户进行访问。您可以生成密钥并下载它,然后将其指向文件夹您已保存它。 (看来您刚刚插入了该信息,这也起作用。)



格式错误的响应错误表示未设置任何响应。这可能是由于多种原因造成的,但通常意味着您的程序由于某种原因而崩溃或无法调用 agent.add()。有关更多信息,请查阅运行操作的日志。 (如果您使用的是Dialogflow内联编辑器,则可以通过转到 https:// console来获取日志。 firebase.google.com/ ,选择您的项目,选择左侧的功能标签,然后选择日志标签。)



<根据代码和错误消息,进行strong>更新。



如错误消息所提示,您调用了 admin.initializeApp()不止一次。仅应在首次配置该功能时执行此操作,而不是在每次调用该功能时执行此操作。初始化一次-可以多次使用。



在您的情况下,可以通过移动要求从 personFacts()函数中导入firebase-admin和对 admin.initializeApp()的调用并放入它们都更靠近顶部-可能紧接在其他 require()调用之后。


Beginner here on programming, I'm working on my free time on a project which is related to Google Assistant, for the first time i'm using the Firebase Realtime Database and don't know how to get the data from there, the code below is in Dialogflow's inline editor, where is category1 2 and 3 inside those are students with credits. I have made some changes and put these three (categories1 2 and 3) in the database picture below, i want to remove these three categories from code and replace it with the ones in realtime database.

Because this is my first time using that database, I don't know how to get that data from there with nodejs.

   
      function categoryac(agent) {
        const categories =  {
          category1: {"Alex" : 25, "Jennifer" : 45, "Justin" : 35, "Peter" : 89},
          category2: {"Alex" : 95, "Jennifer" : 75, "Justin" : 85, "Peter" : 59},
          category3: {"Alex" : 67, "Jennifer" : 55, "Justin" : 45, "Peter" : 15},
        };
        const categoried = agent.parameters["categoried"];
        const categoryAmount = agent.parameters["categoryAmount"];        
        const category = category[categoried];
        const aggregate = category[categoryAmount];       
        agent.add(`${categoried}'s ${categoryAmount} is ${aggregate}`); 
      }

      let intentMap = new Map();
      intentMap.set('category', categoryac);
      agent.handleRequest(intentMap);
    });

UPDATE I used the code below, like this:

  

  function categoryac( agent ){
    const categoried = agent.parameters["categoried"];
    const categoryAmount = agent.parameters["categoryAmount"];
    var admin = require( 'firebase-admin' );
    admin.initializeApp( {
      credential: admin.credential.cert( {
        projectId: ' ',
        clientEmail: ' ',
        privateKey: ' '
      } ),
      dblink: 'www.*****.*****.com'
    } );
    var thing = admin.database();
    var  relating= thing.ref( `category/${categoried}/${categoryAmount}` );
    return relating.once( "value" ).then( snapshot =>{
      var aggregate = snapshot.value();
      agent.add( `${categoried}'s ${categoryAmount} is ${aggregate}` );
    } )
      .catch( fail =>{
        agent.add( 'uh oh, something went wrong.' );
        console.error( fail );
      } );
  }

  let intentMap = new Map();
  intentMap.set( 'category', categoryac );
  agent.handleRequest( intentMap );
} );

got error message : 'MalformedResponse Failed to parse Dialogflow response into AppResponse because of empty speech response.' error from log :

{
 insertId:  "v*****2"  
 labels: {
  channel:  "preview"   
  querystream:  "GOOGLE_USER"   
  source:  "JSON_RESPONSE_VALIDATION"   
 }
 logName:  "projects/****/logs/actions.googleapis.com%2Factions"  
 receiveTimestamp:  "2019-01-07T14:45:29.274840871Z"  
 resource: {
  labels: {
   action_id:  "actions.intent.TEXT"    
   project_id:  "******"    
   version_id:  ""    
  }
  type:  "assistant_action"   
 }
 severity:  "ERROR"  
 textPayload:  "MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response"  
 timestamp:  "2019-01-07T14:45:29.266062732Z"  
 trace:  "projects/383182941858/traces/ABwppHFK_PehMj1XEs_Arng9VL7_zShy-EWvoziK0Ro6v74TaduNG1cJaRMnGAZMoLZhtILdG2hEBkDvJQ"  
}

Here is the error in the logs:

Error: The default Firebase app already exists. This means you called initializeApp() more than once without providing an app name as the second argument. In most cases you only need to call initializeApp() once. But if you do want to initialize multiple apps, pass a second argument to initializeApp() to give each app a unique name. 
at FirebaseAppError.Error (native) 
at FirebaseAppError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28) 
at FirebaseAppError.PrefixedFirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:85:28) 
at new FirebaseAppError (/user_code/node_modules/firebase-admin/lib/utils/error.js:119:28) 
at FirebaseNamespaceInternals.initializeApp (/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:68:23) 
at FirebaseNamespace.initializeApp (/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:362:30) 
at categoryac (/user_code/index.js:34:11) 
at WebhookClient.handleRequest (/user_code/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:303:44) 
at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/user_code/index.js:91:9) 
at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:57:9)

解决方案

There are several things that you'll need to learn.

The first is how to add the Firebase Admin SDK to your project.

You'll also need to learn how to retrieve the data using the library. Firebase uses a reference-path based method to fetch the data, so you need to make sure you build the path correctly.

Finally, since you're doing this inside a fulfillment handler, and you are making an asynchronous call, you need to make sure you return a Promise. Fortunately, fetching the data also involves returning a Promise, so you can return this Promise.

The code might, partially, look something like this (untested):

  function personFacts(agent) {
    const personId = agent.parameters["personId"];
    const personMeasurement = agent.parameters["personMeasurement"];        

    var db = admin.database();
    var ref = db.ref(`person/${personId}/${personMeasurement}`);
    return ref.once("value")
      .then( snapshot => {
        var result = snapshot.val();
        agent.add(`${personId}'s ${personMeasurement} is ${result}`); 
      })
      .catch( err => {
        agent.add('uh oh, something went wrong.');
        console.error( err );
      });

  }

As you noted, you need to initialize the Firebase admin library with a key that will give you access through the service account. You can generate the key and download it, and then point to the folder where you have saved it. (It looks like you've just inlined the information, which also works.)

The "Malformed Response" error means that no response was set. This can be due to a number of things, but generally means that your program crashed or failed to call agent.add() for some reason. Consult the logs of your action running for more info. (If you are using the Dialogflow Inline Editor, you can get to the logs by going to https://console.firebase.google.com/, selecting your project, selecting the "Functions" tab on the left, and selecting the "logs" tab.)

Update based on the code and error message.

As the error message suggests, you called admin.initializeApp() more than once. This should only be done when the function is first configured, rather than each time your function is called. Once initialized once - it can be used multiple times.

In your case, this can be done by moving the require that imports firebase-admin and the call to admin.initializeApp() out of the personFacts() function and put them both closer to the top - probably right after the other require() calls.

这篇关于从实时数据库获取JSON数据到Dialogflow内联编辑器(Google助手)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆