当有数据时,snapshot.val()返回null

时间:2019-01-09 16:39:05

标签: node.js firebase firebase-realtime-database dialogflow

我正在尝试使用Google Assistant在Dialogflow内联编辑器中从Firebase Realtime Database检索信息,但是由于某种原因,我返回了null,Google Assistant回答了person1's Alex is null

我的参考文献定位不正确吗?我是第一次使用dialogflow和实时数据库。

'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
var admin = require('firebase-admin');
admin.initializeApp({
  credential: admin.credential.cert({
    projectId: ' ',
    clientEmail: ' ',
    privateKey: ' '
  }),
  databaseURL: 'https://*****.firebaseio.com'
});
process.env.DEBUG = 'dialogflow:debug';
// enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request,response)=>{
  const agent = new WebhookClient({
    request,
    response
  });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function welcome(agent) {
    agent.add(`Welcome to my agent!`);
  }

  function fallback(agent) {
    agent.add(`I didn't understand`);
    agent.add(`I'm sorry, can you try again?`);
  }

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

  let intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  intentMap.set('person', personFacts);
  agent.handleRequest(intentMap);
});

这是实时数据库: enter image description here

根据建议,我将数字0、1、2更改为person1,person2,person3 对于实时数据库的引用几乎不需要帮助:

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

   const result = pperson[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 );
      });

  }
   let intentMap = new Map();
      intentMap.set('Default Welcome Intent', welcome);
      intentMap.set('Default Fallback Intent', fallback);
      intentMap.set('person', personFacts);
      agent.handleRequest(intentMap);
    });

1 个答案:

答案 0 :(得分:0)

听起来您正在通过询问“ person 1”来询问信息,但是数据库中没有值“ person1”的键。在“人员”层次结构下有一个键“ 1”,也许这就是您想要的。

您有几种选择,具体取决于您要实际执行的操作。

您可以更改密钥以反映您的要求。因此,您可以仅使用“ person1”,“ person2”或“ person3”来代替按键使用“ 0”,“ 1”或“ 2”。您无需在Firebase数据库中使用数字。您可以使用但要引用数据。

另一种选择是将密钥保留在数据库中,并且当人员说“ person1”时,以某种方式将其映射到数据库中正确的密钥(即-“ 0”)。您可以编写代码来执行此操作-在这种情况下,您需要personId参数的子字符串。所以也许像

let personKey = personId.substring(6);

,然后在参考路径中使用personKey

var ref = db.ref( `person/${personKey}/${personMeasurement}` );

但是,这些只是示例-如何执行取决于您要如何构造和访问数据。

重要的部分是了解Firebase数据库如何使您访问数据。数据存储在一个层次结构中,我们可以想到该层次结构中的每个节点都有一条路径。在您的示例中,您在顶部有一个名为“人”的节点。在该节点下,有几个只是数字的节点-一个名为“ 0”的节点就是一个例子。在“ 0”节点下,您有几个节点,其中一个名为“ Alex”。

您可以通过指定特定的“ Alex”节点的完整引用路径来对其进行引用。我们用“ /”分隔每个节点的名称。因此,指向此特定“ Alex”的完整参考路径为person/0/Alex。要在此节点上获取值,我们可以构建一个ref对象,然后使用once("value")一次获取该值(而不是监听更改)。

由于其“ 0”和“ Alex”部分存储在变量中,因此我们需要构建一个包含这些值的字符串。一种简单的方法是在JavaScript中使用template literal或“反引号字符串”。在这种类型的字符串中,${}中的所有内容都会被评估。因此${personKey}的意思是将personKey的值插入字符串。

所以这行

var ref = db.ref( `person/${personKey}/${personMeasurement}` );

表示“创建对数据库节点的引用,从“人”节点开始,然后在该节点下找到具有personKey中值的节点,然后在该节点下找到具有{中值的节点{1}}”。

当然,您可以将personMeasurementpersonKey替换为包含您要在节点层次结构中寻找的值的任何变量。您可以用其他方式构建此字符串,并使用其他工具构建引用。重要的一点是要了解引用是指向数据库中的某个点的,并且您需要先构建此引用,然后才能从该点获取引用。