如何使用dialogflow实现内联编辑器将用户名和心情保存在实时数据库上?

时间:2018-09-29 15:09:02

标签: firebase firebase-realtime-database dialogflow fulfillment

我出于对话目的在Google上使用dialogflow构建了动作。 它的想法是:每天向特定用户询问3次他们的心情。 经过研究人员分析之后,它每周都会向这些用户发送每周一次的有关他们的情绪的概述。

因此,我需要将每个用户的信息以及他的心情条目保存在数据库中,以便研究人员以后可以访问它们,对其进行分析并发回给用户。

我正在使用带有index.js的dialogflow实现来连接到Firebase数据库以保存条目。 此代理应作为对Google的操作进行整合

在数据库上,我获得了用户名和心情,但是它们彼此无关,所以我不知道哪个用户输入了哪种心情,也无法进行userID检查。

如果有人完全不熟悉node.js或数据库,但是如果我必须那样做,我将不胜感激。

这是我的代码。

RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ 
index.php?pageid=$1&pageid=$2&pageid=$3 [NC,L] 
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php? 
pageid=$1&pageid=$2 [NC,L] 
RewriteRule ^([A-Za-z0-9-]+)/$ index.php?pageid=$1 [NC,L] 

1 个答案:

答案 0 :(得分:1)

您的代码和方法中有一些需要解决的问题:

  • 您需要设计数据库,以便可以将用户的心情与他们的帐户相关联。 (可能还有其他用户信息,例如您在访问时的名称或电子邮件地址。)
  • 您需要此人的唯一身份。
    • 一个人的名字不是唯一的身份。两个人的名字可能相同,或者系统每次听到的名字都不相同,因此您需要一种方法来知道与谁通话。
    • 您还需要知道他们的电子邮件地址和其他信息,以便您可以在周末将其报告发送给他们。
  • 您需要确保在同一对话期间两次调用您的操作之间具有自己的身份。

幸运的是,您做了一件通常会错过的事情-您使用Promises对数据库进行了调用。这样就可以了。

唯一身份

您的示例代码向用户询问其名称,这听起来像您打算用作其身份。不幸的是,由于以下几个原因,这是一个坏主意:

  • 名称不是身份。如果两个同名的人访问您的操作会怎样?

  • 名称很容易发现,因此其他人可以使用它并报告误导性信息。在您的情况下,这可能不太严重,但仍可能会影响信任度。

  • 名称可以是个人身份信息(PII),因此可能会受到其他隐私法的保护。

  • 用户可能想要终止其帐户,并且如果不“更改”其名称就无法执行此操作。

此外,您稍后可能需要其他身份信息,例如其电子邮件地址,并且每次询问都可能变得麻烦。

您有几种方法可以解决此问题:

  • 如果您正在开发Google助手,还可以使用Google Sign In for Assistant来告诉您用户的Google标识符,您可以将其用作唯一ID。您还将在其个人资料中获得他们的电子邮件地址和姓名。

  • 您可以要求提供此信息(名称,电子邮件等),并将其保存在生成​​的用户ID或用户提供的用户名中。该ID成为标识符。如果您正在开发Google助手,则可以将该ID保存在用户的私有存储中-只有您和用户可以访问或删除它。如果不是,则可能需要使用数据库来查找ID。稍后会对此进行更多介绍。

  • 稍后您可能希望使用变体,具体取决于您获取的信息以及您希望用户每次如何标识自己的身份。但是重要的是,他们需要用独特的东西来识别自己,并且您可以轻松地捕获它们。

在同一会话中使用身份

如果您使用的是Google登录,则不必为此担心。您将在每个会话中以及会话期间的每个呼叫获得相同的ID。

如果您将用户的私有存储与Google助手一起使用,则将其作为userStore对象的一部分。

但是,如果不是这样,则需要确保尽早获得用户的ID,并将其保存为Context的一部分,以便在两次Webhook调用之间保留该ID。在后续处理程序中,您可以从上下文中获取ID,然后使用它来访问其他信息。

此时,您不需要将其存储在数据库中。您所拥有的只是一个标识符-这将成为您用于其他信息的 key 。您只需要记住它即可在以后的对话中使用。

因此,在您的saveName()函数中,它可能看起来像

   function saveName(agent) {
       const nameParam = agent.parameters.name;
       agent.add('Hi ' + nameParam + ' Are you ready to answer my question?');
       agent.setContext({
         name: 'user',
         lifespan: 99,
         parameters: {
           id: nameParam
         }
       };
   }

顺便说一句-您的管理员似乎试图确定这是用户说出他们的名字还是确认他们的名字。这可能更好地作为单独的意图和单独的处理程序进行处理。试图将它们结合起来会使事情变得混乱。

构建和访问数据库

我们有一个ID。我们让用户报告数据。我们如何将两者联系起来?

有许多种结构化数据的方法,Firebase会根据您打算如何使用它,访问它并使它对用户或其他用户可用而详细介绍。

在这种情况下,要存储有关用户的记录似乎很简单。每个记录可以使用其ID作为键,然后包含有关用户的一些信息,包括他们的心情。

关于Firebase数据库的一件好事是,您可以(大部分)将其像Javascript对象一样对待。如果我们这样考虑,它可能看起来像

{
  "user": {
    "id1":{...},
    "id2":{...},
    "id3":{
       "moods": [
         {"mood":"good"},
         {"mood":"tired"}
       ]
    },
    "id4":{...}
  }
}

等等。使用Firebase,我们将使用user/id3/moods之类的路径引用用户“ id3”的心情。如果我们将用户ID包含在变量name中,则可以使用以下代码获取该引用

var ref = admin.database().ref('user').ref(name).ref('moods');

然后使用诸如此类的代码将带有心情的对象推入数组(并返回我们需要做的Promise):

var obj = {
  mood: mood
};
return ref.push( obj ).then( snapshot => {
  // Do stuff, including acknowledge to the user you saved it.
});

请记住,您可能还希望使用它在用户级别存储有关每个用户的更多信息(例如,他们的姓名或电子邮件),或者存储更多有关心情对象中的情绪(例如时间戳)的信息。