【问题标题】:Firebase Query in Functions not returning as expected函数中的 Firebase 查询未按预期返回
【发布时间】:2018-01-25 22:42:01
【问题描述】:

我正在尝试做一些相当简单的事情,但在获得预期的行为时遇到了很多麻烦。在由外部 HTTP 调用触发的 firebase 函数中,我试图根据我在 HTTP 调用中获得的值从 Firebase 数据库中提取一个对象。

奇怪的是,基本上相同的代码在我的网络应用程序中工作(使用角度),但在函数中不起作用(基于节点)。

这是数据库结构:

ROOT
/users
    /-L1toTQ_nLwyy2jhuz1h
        /athlete
            /name
            /id
            /country
    /-L1twwvmpAvBI80uHpFc
        /athlete
            /name
            /id
            /country

在我使用 Javascript (Angular) 构建的网络应用程序上,以下函数按我的预期返回快照。我在每个用户中搜索(不知道唯一 ID (-L1toTQ_nLwyy2jhuz1h)。相反,我正在搜索嵌套在 users/{unique}/athlete/... 下的 id,这符合我的预期。

这可行

var fire = firebase.database();
var externalID = 12345;
var users = fire.ref('users');
var query = users.orderByChild('athlete/id').equalTo(externalID);

query.once('value', function(snap){
  var k = Object.keys(snap.val())[0]; //gets the key of the first result
  var user = snap.val(); // sets user = full returned object from firebase
  console.log(user[k]); // logs below
});

正如预期的那样,这是用户 [k] 记录到控制台的内容:

{
"athlete": {
    "country": "United States",
    "name": "Jack",
    "id": 12345,
    }
}

我使用该代码作为编写云函数的基础,但无法获得类似的结果。取而代之的是snap.val() = nullsnap.key = 'users'。这意味着当我尝试运行var k = Object.keys(snap.val())[0]时出现错误

这行不通

var admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
var db = admin.database();

exports.incomingTest = functions.https.onRequest((request, response) => {

    const externalId = 12345;

    const users = db.ref('users');
    const query =  users.orderByChild('athlete/id').equalTo(externalId);

    query.once('value').then(snap => {
        console.log(snap.val()); // logs null
        console.log(snap.key);  // logs 'users'


    }).catch(reason =>{
        console.log(reason);
     });
    response.send(200)
});

我已经尽可能多地环顾四周,有些地方说你不能深入查询多个级别,但我可以从网络应用程序中清楚地查询......所以我不明白为什么它没有无法从云功能中工作。另外,我发现一篇文章说 Firebase 添加了深度查询多个级别的功能。

我之前也收到一个错误,说我正在搜索非索引变量,所以我将它添加到我的规则中,我不再收到该错误。

{
 "rules": {
         ".read": "auth != null",
         ".write": "auth != null",
         "users": {
                 ".indexOn": "athlete/id"
                  }
          }
 }

最后,我没有收到来自query.once() 函数的错误响应(注意.catch())。但我实际上得到了成功返回的snap,但它是空的。

【问题讨论】:

    标签: javascript firebase firebase-realtime-database google-cloud-functions


    【解决方案1】:

    我不完全确定这是否会解决您的特定问题,但我可以告诉您,您没有正确编写 HTTPS 类型函数。 HTTPS 函数在发送响应后终止。在您的情况下,您在技术上数据库查询完成之前发送响应(因为on() 是异步的,它会立即返回)。

    尝试这样编写,以确保您的数据库查询在发送响应之前完成:

    query.once('value').then(snap => {
        console.log(snap.val()); // logs null
        console.log(snap.key);  // logs 'users'
        response.send('ok')  // note: send does not take a status code
    }).catch(reason =>{
        console.log(reason);
        response.status(500).send('not ok')
    });
    

    另请注意,我已更正您对回复的使用。

    【讨论】:

    • 感谢您的建议。我一直在查看服务器日志以查看从我的query.once() 函数中注销的内容,而不用担心请求返回的内容。很高兴知道这一点,一旦我弄清楚其余部分,我会确保更新。
    • 但是你应该担心它,因为如果你提前终止它,你的函数可能会表现得很奇怪。您将提前终止它。
    • 哦,我明白你的意思了。这就说得通了。谢谢,这似乎确实解决了它。我想我提前终止它会变得奇怪。谢谢!这让我发疯了。
    • 如果此答案对您有用,请接受它作为正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多