如何在Cloud Functions的Cloud Functions中访问多个实时数据库实例

ste*_*osf 6 javascript firebase firebase-realtime-database google-cloud-functions firebase-admin

我在Firebase项目中使用多个数据库.主(默认)数据库的云功能很好,但是,我不能使它们适用于辅助数据库.例如,我想在具有管理员权限的节点上发出读取请求:

//this works
admin.database().ref(nodePath).once('value')...
Run Code Online (Sandbox Code Playgroud)

这适用于主数据库,但是,如果我想在另一个数据库上执行该命令,它不起作用:

//this doesn't work
admin.database(secondaryDatabaseUrl).ref(nodePath).once('value')...
Run Code Online (Sandbox Code Playgroud)

虽然部署了这些功能,但在尝试执行云功能时,我在控制台上收到错误.

以下是带有https触发器的云功能代码:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const secureCompare = require('secure-compare');

exports.testFunction= functions.https.onRequest((req, res) => {
  const key = req.query.key;
  // Exit if the keys don't match
  if (!secureCompare(key, functions.config().cron.key)) {
    console.error('keys do not match');
    res.status(403).send('error1');
    return;
  }
  //test read request
  //the line below crashes the function
  return admin.database('https://secondary_db_url.firebaseio.com').ref(`/testNode`).once('value').then(dataSnapshot=> {
    console.log('value', dataSnapshot.val());
    return;
  }).catch(er => {
    console.error('error', er);
    res.status(403).send('error2');
  });
});
Run Code Online (Sandbox Code Playgroud)

以下是Firebase控制台中的错误日志:

TypeError: ns.ensureApp(...).database is not a function
    at FirebaseNamespace.fn (/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:251:42)
    at exports.testFunction.functions.https.onRequest (/user_code/index.js:16:16)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:26:41)
    at /var/tmp/worker/worker.js:671:7
    at /var/tmp/worker/worker.js:655:9
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
Run Code Online (Sandbox Code Playgroud)

如果我没有指定辅助数据库URL,该函数将在我的主数据库上生成读取请求,该请求非常有效:

//this works
return admin.database().ref(`/testNode`).once('value').then(dataSnapshot=> {
...
Run Code Online (Sandbox Code Playgroud)

我正在使用最新的SDK版本:"firebase-admin": "^5.5.1""firebase-functions": "^0.7.3"

那么,如何使用管理员权限在云功能中获取辅助数据库的实例?

Hir*_*aka 13

以下是使用Admin SDK按URL访问数据库的方法:

let app = admin.app();
let ref = app.database('https://secondary_db_url.firebaseio.com').ref();
Run Code Online (Sandbox Code Playgroud)

以下是Admin SDK集成测试的示例:https://github.com/firebase/firebase-admin-node/blob/master/test/integration/database.js#L52


Gui*_*dre 9

现在有了云功能 > 1.1,这里是在这个问题上救了我一命的文档链接。

https://firebase.google.com/docs/database/usage/sharding#connect_your_app_to_multiple_database_instances

所以,它在我的云函数 index.js 的顶部看起来像这样:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const dev = admin.initializeApp({
  databaseURL: "https://appdev.firebaseio.com"
}, 'dev');

const v2 = admin.initializeApp({
  databaseURL: "https://appv2.firebaseio.com"
}, 'v2');
Run Code Online (Sandbox Code Playgroud)

然后,在我的克隆函数函数代码中,我可以执行以下操作:

//will change stuff on default database
admin.database().ref().child(`stuff/${stuffId}`).set(myStuff)

//will change stuff on my dev database
admin.database(dev).ref().child(`stuff/${stuffId}`).set(myStuff)

//will change stuff on my v2 database
admin.database(v2).ref().child(`stuff/${stuffId}`).set(myStuff)
Run Code Online (Sandbox Code Playgroud)


Dou*_*son 8

因此,您似乎尝试使用javascript Web客户端API访问多个数据库.将数据库的URL传递给这样的API不适用于Admin SDK:

admin.database('https://secondary_db_url.firebaseio.com').ref(`/testNode`)
Run Code Online (Sandbox Code Playgroud)

相反,您必须初始化第二个应用程序,为其命名,然后将该应用程序传递给Admin SDK API.这是一个完整的示例,它将相同的数据写入同一项目中的两个不同的数据库实例:

const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)

const otherConfig = Object.assign({}, functions.config().firebase)
otherConfig.databaseURL = 'https://your-other-db.firebaseio.com/'
const otherApp = admin.initializeApp(otherConfig, 'otherAppName')

exports.foo = functions.https.onRequest((req, res) => {
    const data = { foo: 'bar' }
    const p1 = admin.database().ref('data').set(data)
    const p2 = admin.database(otherApp).ref('data').set(data)
    Promise.all([p1, p2]).then(() => {
        res.send("OK")
    })
    .catch(error => {
        res.status(500).send(error)
    })
})
Run Code Online (Sandbox Code Playgroud)


Zac*_*ack 6

在 Firebase Functions v3.14.0 上更新此内容。这些答案都不适合我,所以我实施了这个解决方案

实例注册一个函数,该函数会触发来自特定 Firebase 实时数据库实例的事件

functions.database.instance('my-app-db-2').ref('/foo/bar')
Run Code Online (Sandbox Code Playgroud)

使用数据库实例的名称即可运行,无需 url。在没有实例的情况下使用functions.database.ref监视事件的默认实例。