web-dev-qa-db-ja.com

Cloud Functions forFirebaseで複数のRealtimeDatabaseインスタンスにアクセスする方法

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"

では、管理者権限を使用してクラウド機能でセカンダリデータベースのインスタンスを取得するにはどうすればよいですか?

9
steliosf

AdminSDKを使用してURLでデータベースにアクセスする方法は次のとおりです。

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

13

したがって、javascriptWebクライアントAPIを使用して複数のデータベースにアクセスしようとしているようです。このようにデータベースのURLをAPIに渡すことは、AdminSDKでは機能しません。

admin.database('https://secondary_db_url.firebaseio.com').ref(`/testNode`)

代わりに、 2番目のアプリを初期化する 、名前を付け、そのアプリをAdmin SDKAPIに渡す必要があります。これは、同じプロジェクト内の2つの異なるデータベースインスタンスに同じデータを書き込む完全なサンプルです。

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)
    })
})
8
Doug Stevenson

クラウド機能が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');

そして、私のクローン関数関数コードで私ができること:

//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)
4

したがって、両方の答えが機能しない場合。

私に起こったことは、両方の方法がエラーなしで機能したが、データベースの2番目のインスタンスが更新されていなかったことです。

NpmとfirebaseCLIを更新しました。

また、@ DoughStevensonあなたPassing the URL of the database to the API like this **does** work with the Admin SDK

そして、これはほぼ同じFirebaseの優れたブログです Firebaseブログ:マルチデータベースのサポートによりスケーリングが簡単になります!

0
purush