函数中的Firebase查询未按预期返回

时间:2018-01-25 22:42:02

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

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

奇怪的是,基本上相同的代码在我的Web应用程序中工作(使用angular),但它在函数(基于Node)中不起作用。

这是数据库结构:

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

在我使用Javascript(Angular)构建的web应用程序中,以下函数返回我期望的快照。我在每个用户中搜索(不知道唯一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,但它为空。

1 个答案:

答案 0 :(得分: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')
});

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