Firebase自动生成密钥时,是否可以更新孩子的数据?

时间:2019-04-29 07:31:01

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

当Firebase自动生成密钥时,我正在尝试更新特定数据。

我尝试了下面的代码。它仍然不起作用:(

我已经尝试过:

  function updateHomeworkStatus(agent) {

    var chosenHw = request.body.queryResult.outputContexts[0].parameters.chosenHw;
    var status = request.body.queryResult.outputContexts[0].parameters.status;

    var query = admin.database().ref('Homework').orderByChild('Name').equalTo(chosenHw);
    query.once('value')
      .then(snapshot => {
        // Once we have a result, we can use the reference to it
        var snapshotRef = snapshot.ref;

        // We want to change the value of Completed field, 
        // so we get a reference to that
        var completedRef = snapshotRef.child('CompletionStatus');

        // We can then set it, since we have a direct reference to the
        // field and there is nothing else that will be changed.
        completedRef.update(status);
      });

    agent.add("Status has been changed to " + status);


  }

例如(我附上了我的Firebase图片)

Dialogflow:您要更改的作业的名称是什么             完成状态? (我已经做到了)

,并且当用户说“ Coding Worksheet 7”和所需状态为“是”时, 具体数据将被更改。 (此编码部分需要使用hep。)

因此,预期结果将是“ Coding Worksheet 7”的CompletionStatus更改为“ No”。

My Firebase

1 个答案:

答案 0 :(得分:2)

当前解决方案的关键问题是Firebase RT Database调用是异步的,并且在响应用户之前,您不必等待这些调用返回结果。

此外,Firebase RT Database Queries将返回结果列表/集合。因此,要查看查询结果,必须使用snapshot.forEach()对返回的数据进行迭代。

如果要使用更新操作update(),则传递给函数的参数必须是包含'path/to/value': value对的对象。有关更多信息,请参见此Firebase Blog post。因此,对于您的代码,您可以使用`update({CompletionStatus:status})更新'CompletionStatus',而不必担心完全使用child()。

您还需要考虑错误情况,例如不存在的文件,重复的名称和Firebase RTDB错误。我在下面添加了这些错误处理支架。

// somewhere near the top of your request handler
const RESULT_NOT_FOUND = -1;
const RESULT_DUPLICATED = -2;

function updateHomeworkStatus(agent) {
  var outputContext = request.body.queryResult.outputContexts[0];
  var chosenHw = outputContext.parameters.chosenHw;
  var status = outputContext.parameters.status;

  var query = admin.database().ref('Homework').orderByChild('Name').equalTo(chosenHw);

  // Remember to return the promise
  return query.once('value')
    .then(snapshot => {
      // "snapshot" is the query result, it's children contain the queried data

      if (!snapshot.hasChildren()) {
          throw RESULT_NOT_FOUND;
      } else if (snapshot.numChildren() != 1) {
          throw RESULT_DUPLICATED;
      }

      // init variable to store DatabaseReference
      var firstResultRef;

      // only one child at this point, so only called once
      snapshot.forEach(childSnapshot => {
        firstResultRef = childSnapshot.ref;
        return true; // stop looping
      });

      // Update 'CompletionStatus' with new value (using update() to protect existing data)
      // Remember to return the promise
      return firstResultRef.update({ CompletionStatus: status });
    })
    .then(() => { // Promise.then(successHandlerFunc, errorHandlerFunc)
      // success
      agent.add("Status has been changed to " + status);
    }, (err) => {
      // failure
      if (err === RESULT_NOT_FOUND) {
        agent.add("Sorry, I couldn't find '" + chosenHw + "'.");
      } else if (err === RESULT_DUPLICATED) {
        agent.add("Sorry, I found multiple files that match '" + chosenHw + "'.");
      } else {
        // if here, a database error has occurred.
        agent.add("Sorry, I could not process that request at this time.");
        // TODO: Log error "err".
      }
    });
}