如何在 Cloud Functions for Firebase 中访问多个实时数据库实例
How to access multiple Realtime Database instances in Cloud Functions for Firebase
我在一个 Firebase 项目中使用多个数据库。主(默认)数据库的云函数工作得很好,但是,我不能让它们为辅助数据库工作。例如,我想在具有管理员权限的节点上发出读取请求:
//this works
admin.database().ref(nodePath).once('value')...
这在主数据库中有效,但是,如果我想在另一个数据库上执行该命令,它不起作用:
//this doesn't work
admin.database(secondaryDatabaseUrl).ref(nodePath).once('value')...
虽然部署了函数,但在尝试执行云函数时控制台出现错误。
这是带有 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');
});
});
以下是 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)
如果我不指定辅助数据库 URL,该函数将在我的主数据库上发出读取请求,效果很好:
//this works
return admin.database().ref(`/testNode`).once('value').then(dataSnapshot=> {
...
我使用的是最新的 SDK 版本:"firebase-admin": "^5.5.1"
和 "firebase-functions": "^0.7.3"
那么,如何使用管理员权限在云函数中获取辅助数据库的实例?
看来您正在尝试使用 javascript 网络客户端 API 访问多个数据库。像这样将数据库的 URL 传递给 API 不适用于 Admin SDK:
admin.database('https://secondary_db_url.firebaseio.com').ref(`/testNode`)
相反,您必须 initialize a second app,为其命名,然后将该应用传递给 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)
})
})
以下是 URL 使用 Admin SDK 访问数据库的方法:
let app = admin.app();
let ref = app.database('https://secondary_db_url.firebaseio.com').ref();
以下是来自 Admin SDK 集成测试的示例:https://github.com/firebase/firebase-admin-node/blob/master/test/integration/database.js#L52
因此,如果两个答案都不起作用。
发生在我身上的是这两种方法都没有任何错误,但数据库的第二个实例没有得到更新。
我更新了它工作的 npm 和 firebase CLI。
还有@Dough Stevenson 你Passing the URL of the database to the API like this **does** work with the Admin SDK
这是来自 Firebase 的一个很好的博客
Firebase Blog : Easier scaling with multi-database support!
现在有了云功能 > 1.1,这里是文档 link 在这个问题上救了我的命。
所以,在我的云函数 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');
然后,在我的克隆函数中我可以做的函数代码:
//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)
在 Firebase Functions v3.14.0 上更新此内容。 None 个答案对我有用,所以我实施了 this solution
instance 注册一个触发来自特定 Firebase 实时数据库实例的事件的函数
functions.database.instance('my-app-db-2').ref('/foo/bar')
使用数据库实例的名称即可,不需要 url。 functions.database.ref 在没有实例的情况下使用监视事件的默认实例。
我在一个 Firebase 项目中使用多个数据库。主(默认)数据库的云函数工作得很好,但是,我不能让它们为辅助数据库工作。例如,我想在具有管理员权限的节点上发出读取请求:
//this works
admin.database().ref(nodePath).once('value')...
这在主数据库中有效,但是,如果我想在另一个数据库上执行该命令,它不起作用:
//this doesn't work
admin.database(secondaryDatabaseUrl).ref(nodePath).once('value')...
虽然部署了函数,但在尝试执行云函数时控制台出现错误。
这是带有 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');
});
});
以下是 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)
如果我不指定辅助数据库 URL,该函数将在我的主数据库上发出读取请求,效果很好:
//this works
return admin.database().ref(`/testNode`).once('value').then(dataSnapshot=> {
...
我使用的是最新的 SDK 版本:"firebase-admin": "^5.5.1"
和 "firebase-functions": "^0.7.3"
那么,如何使用管理员权限在云函数中获取辅助数据库的实例?
看来您正在尝试使用 javascript 网络客户端 API 访问多个数据库。像这样将数据库的 URL 传递给 API 不适用于 Admin SDK:
admin.database('https://secondary_db_url.firebaseio.com').ref(`/testNode`)
相反,您必须 initialize a second app,为其命名,然后将该应用传递给 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)
})
})
以下是 URL 使用 Admin SDK 访问数据库的方法:
let app = admin.app();
let ref = app.database('https://secondary_db_url.firebaseio.com').ref();
以下是来自 Admin SDK 集成测试的示例:https://github.com/firebase/firebase-admin-node/blob/master/test/integration/database.js#L52
因此,如果两个答案都不起作用。
发生在我身上的是这两种方法都没有任何错误,但数据库的第二个实例没有得到更新。
我更新了它工作的 npm 和 firebase CLI。
还有@Dough Stevenson 你Passing the URL of the database to the API like this **does** work with the Admin SDK
这是来自 Firebase 的一个很好的博客 Firebase Blog : Easier scaling with multi-database support!
现在有了云功能 > 1.1,这里是文档 link 在这个问题上救了我的命。
所以,在我的云函数 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');
然后,在我的克隆函数中我可以做的函数代码:
//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)
在 Firebase Functions v3.14.0 上更新此内容。 None 个答案对我有用,所以我实施了 this solution
instance 注册一个触发来自特定 Firebase 实时数据库实例的事件的函数
functions.database.instance('my-app-db-2').ref('/foo/bar')
使用数据库实例的名称即可,不需要 url。 functions.database.ref 在没有实例的情况下使用监视事件的默认实例。