Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Access not-default firestore database in function onDocumentCreated()

Hello Dears,

 

I have added another firestore database to my Firebase project, and when I want to trigger the 

onDocumentCreated('surveys/{surveyId}), 
 
I have tried to change the path to ->
1-
  onDocumentCreated('not-default-database-id/surveys/{surveyId},
 
2- 
const otherDb = getFirestore('not-default-database-id')
const colRef = otherDb.collection('surveys/{surveyId}');
 onDocumentCreated(colRef ,
 
But still, The function is not triggered at all.
 
Could you please help me how to access the otherDb?
 
 
0 9 5,623
9 REPLIES 9

Hello @AmaFB,

To access a non-default Firestore database in your Cloud Function's onDocumentCreated trigger, you need to correctly initialize and reference the other database. Here’s how you can do it:

1. Initialize the other Firestore database in your function:

const admin = require('firebase-admin');

admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'https://<your-not-default-database-id>.firebaseio.com'
});

const otherDb = admin.firestore();

2. Use Firestore triggers correctly. Unfortunately, Firestore triggers like onDocumentCreated can only listen to the default Firestore instance . directly. However, you can still use onDocumentCreated to detect changes in the default Firestore and then manually read or write to the other database.

Here’s an example:

exports.onSurveyCreated = functions.firestore
.document('surveys/{surveyId}')
.onCreate(async (snap, context) => {
const newSurvey = snap.data();
const surveyId = context.params.surveyId;

// Now write to the other Firestore database
await otherDb.collection('surveys').doc(surveyId).set(newSurvey);

console.log('Survey written to other database');
});

By doing this, you listen to the default Firestore instance and then manually perform operations on your non-default Firestore instance.

Hope this helps! 

If you have any doubt feel free to ask.

Hello catherinwilliam ; 

Many thanks for your response, 

But I found this: https://firebase.google.com/docs/reference/functions/2nd-gen/node/firebase-functions.firestore.docum...

which means you can define it like this: 

 onDocumentCreated({
  document: 'surveys/{surveyId}',
  database: 'otherDb'
},

Hope this is true! 

When I ran the above code I got :

ERROR 2024-06-09T05:02:46.843235Z Error: 3 INVALID_ARGUMENT: The request was for database 'projects/project-id/databases/(default)' but was attempting to access database 'projects/project-id/databases/otherDb' at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19) 

Hey @AmaFB 

To solve the issue of triggering a Firestore function on a document creation in a non-default Firestore database, here is a step-by-step, human-friendly guide:

1. Initialize the Other Firestore Database

First, you need to initialize the Firestore database you want to access. This is done by setting up Firebase Admin SDK to point to your non-default Firestore database:

const admin = require('firebase-admin');

admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'https://<your-not-default-database-id>.firebaseio.com'
});

const otherDb = admin.firestore();

2. Set Up Firestore Trigger on Default Database

Firestore triggers like onDocumentCreated can only listen to events on the default Firestore database. You can use these triggers to detect changes and then manually perform operations on the non-default database.

Here’s how you can set up a trigger to listen to document creations in the default Firestore database and then copy the data to the other Firestore database:

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

const otherDb = admin.firestore();

exports.onSurveyCreated = functions.firestore
.document('surveys/{surveyId}')
.onCreate(async (snap, context) => {
const newSurvey = snap.data();
const surveyId = context.params.surveyId;

// Write to the other Firestore database
await otherDb.collection('surveys').doc(surveyId).set(newSurvey);

console.log('Survey written to other database');
});

3. Note About Cross-Databases Operations

As of now, Firestore triggers do not support direct operations on non-default databases. The approach is to use the default database to detect changes and then perform the required operations on the other database manually, as shown above.

4. Clarifying the Error and Documentation

You mentioned finding documentation suggesting you can specify a different database directly in the trigger. However, if you're encountering errors like:

3. Note About Cross-Databases Operations

As of now, Firestore triggers do not support direct operations on non-default databases. The approach is to use the default database to detect changes and then perform the required operations on the other database manually, as shown above.

4. Clarifying the Error and Documentation

You mentioned finding documentation suggesting you can specify a different database directly in the trigger. However, if you're encountering errors like:

Error: 3 INVALID_ARGUMENT: The request was for database 'projects/project-id/databases/(default)' but was attempting to access database 'projects/project-id/databases/otherDb'

This means the feature might not be fully supported or there could be a misconfiguration. Stick to using the default database for triggers and then manually interacting with other databases.

Summary

  1. Initialize the non-default Firestore database properly.
  2. Set up triggers in the default database.
  3. Manually handle data operations to/from the non-default database in your trigger functions.

By following these steps, you should be able to achieve the desired functionality of accessing and manipulating data in a non-default Firestore database.

If you have any query then feel free to connect with me.

 

Hello @catherinwilliam,

Thank you so much for your response! 😊

In my case, I added another non-default database and set it up to act as my default. This means that whenever I create a document, it gets created in the non-default database.

Due to this setup, the trigger from the default database cannot be activated.

From your explanation, I understand that it is not possible to trace the onDocumentCreated() trigger in a non-default database.

Kind Regards,

Amro

Hi @catherinwilliam ,

I think what you said here "Firestore triggers like onDocumentCreated can only listen to events on the default Firestore database." is not right, I actually managed to make a cloud function react to a document creation in a secondary database in the same project... the structure of my project is this one:

 

import {onDocumentCreated} from "firebase-functions/v2/firestore";
 
export const addCommentsToTestDB = onDocumentCreated({document: "battles/{battleId}/comments/{commentsId}", database: "testing"}, async (event) =>
{cloud function logic}
 
with that structure, by creating a document in that path in the secondary database named testing, the cloud function starts without problems...
 
My issue is that till now I haven't managed to read, write and update documents in the secondary database in the cloud functions logic, I have tried everything, creating a second instance that points to the testing database in many different ways (including the one you're posting here) but it always points to the default database and crash because is looking for documents that aren't in that database.
 
Here is the structure of the second instance I'm trying to create: 
const testingDatabase = admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  projectId: "xxxxxxxx-xxxxxx",
}, "testingApp");
const testingFirestore = testingDatabase.firestore();
testingFirestore.settings({ignoreUndefinedProperties: true});
 
and then inside the cloud function logic, it crash when I perform actions like: 
 
const writeBatch = testingFirestore.batch();
          writeBatch.create(testingFirestore.collection("battles").doc(event.params.battleId).collection("comments")
            .doc("00_condensedComments"), {"commentsArray": newCondensedArray, "type": "condensedDocument", "limit": limit});
          writeBatch.update(testingFirestore.collection("battles").doc(event.params.battleId).collection("comments").doc(event.params.commentsId), {"position": commentData.position, "condensedNumber": commentData.condensedNumber});
          return writeBatch.commit();
 
because the instance still points to the default database like the error says:
 
Error: Error: 5 NOT_FOUND: No document to update: projects/freejuezstyle-244321/databases/(default)/documents/battles/6B6nVG9ZK0WJRqFiSZ8V/comments/dMx5HuKdF4bZrpCXZocy
at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:192:76)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:141)
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181)
at /workspace/node_modules/@grpc/grpc-js/build/src/resolving-call.js:94:78
at processTicksAndRejections (node:internal/process/task_queues:78:11)
for call at
at ServiceClientImpl.makeUnaryRequest (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:160:34)
at ServiceClientImpl.<anonymous> (/workspace/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
at /workspace/node_modules/@google-cloud/firestore/build/src/v1/firestore_client.js:227:29
at /workspace/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
at repeat (/workspace/node_modules/google-gax/build/src/normalCalls/retries.js:80:25)
at /workspace/node_modules/google-gax/build/src/normalCalls/retries.js:118:13
at OngoingCallPromise.call (/workspace/node_modules/google-gax/build/src/call.js:67:27)
at NormalApiCaller.call (/workspace/node_modules/google-gax/build/src/normalCalls/normalApiCaller.js:34:19)
at /workspace/node_modules/google-gax/build/src/createApiCall.js:84:30
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Caused by: Error
at WriteBatch.commit (/workspace/node_modules/@google-cloud/firestore/build/src/write-batch.js:433:23)
at /workspace/lib/index.js:2172:39
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async /workspace/lib/index.js:2056:12

@andrescoppo 
Hi Andre.  Solution here: GitHub - Accessing Multiple Firestore Databases and Service Accounts In The Admin SDK 

We create a friendly function of the Firebase Admin SDK that allows us to freely navigate between databases and service accounts. Since the imports are modular, the global namespace allows us to freely access the object that is our various apps and databases.

EXAMPLES:

var ProfileDoc = await FDB({db:'abc',path:${path}/profiles/account}).get()

var AuthCollection = FDB({db:'xyz',path:'firewall'})

var Query = await FDB({}) .where('userId','==',userId) .get()

Note the FDB is synchronous, so the await applies to the get(), since we have a document or collection reference. Note that passing no parameters to FDB returns the default firestore.

Thanks for your answering

Example of a working solution updating multiple databases within the same project: https://gist.github.com/mtio/487d300aa4da54488ef90628ea516898