How to create collections in cloud firestore dynamically from cloud functions - firebase

I am trying to create collections and sub collections for document inside a collection dynamically from cloud functions,
But I am getting following exception
**
Argument "collectionPath" must point to a collection, but was
"data/c2f7c4e84366". Your path does not contain an odd number of
components
**
Logs -
Error: Argument "documentPath" must point to a document, but was "exports/user343434_inbox/profile". Your path does not contain an even number of components.
at Firestore.doc (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/firestore/src/index.js:282:13)
at admin.firestore.doc.set.then.ws (/user_code/lib/index.js:28:53)
code snippet:
const p = admin.firestore().doc(exports/${userInboxCollectionName}/profile).set(reqData, { merge: false })
*
I am expecting cloud function to create the subcollection(userid_inbox) inside exports collection(already exists) dynamically if not exists and add the profile document.

Firestore works like this: collection / document / subCollection / "subDocument" / and so on.
You should try: (I'm using TS)
let p = admin.firestore().collection(`exports/${userUID}/${theSubcollection}`)
.add({ message: messageString })
.then(ref => {
console.log('Added document with ID: ', ref.id)
});
//let's see the estructure here:
//collection.......exports
//document.........${userUID}
//subcollection....${theSubcollection}
//document.........ref.id
//data.............message with value messageString
with this code you are creating an new document with the value message on a new subcollection.

Related

Firestore force create ancestor documents

I'm creating a firestore document that's not at the root level of an existing collection but somewhat deeper:
const response = await addDoc(
collection(
firestore,
'stats', //collection
'dayStats', //document
'years', //collection
'2023', //document
'january', //collection
),
statData
);
At the time of creation, the entire collection structure does not yet exist, but only a part of it (stats/dayStats/years).
What ends up happening is that stat document is successfully created in the correct place, but not the intermediary documents. They are in italics and there's a warning for them saying "This document does not exist, it will not appear in queries or snapshots".
I suppose this means that I need to be explicit about force creating these intermediary documents? Is there some kind of a config I can pass to the function, that would just create the intermediary documents in the path, if they to not yet exist? Or do I need to do this by hand each time I'm creating a document, that has a ancestor document that might not exist?
The intermediary documents are in italics and there's a warning for them saying "This document does not exist, it will not appear in queries or snapshots". I suppose this means that I need to be explicit about force creating
these intermediary documents?
Indeed the intermediary parent documents don't exist and you need to create them.
Is there some kind of a config I can pass to the function, that would
just create the intermediary documents in the path, if they to not yet
exist?
No
Do I need to do this by hand each time I'm creating a document, that
has a ancestor document that might not exist?
Yes you need, in your code, to create the parent documents. The best is to use a Batched Write which ensures that both the parent and children docs are created via an atomic operation.
For example:
import { writeBatch, doc } from "firebase/firestore";
const batch = writeBatch(firestore);
const ref1 = doc(firestore, "stats", "dayStats");
batch.set(ref1, {...});
const ref2 = doc(ref1, "years", "2023");
batch.set(ref2, {...});
const ref3 = doc(ref2, "january"); // DocID will be auto-generated
batch.set(ref3, statData);
await batch.commit();

How to create a Firebase Cloud Function for a Document Created on a Collection inside of another Document and Collection

I have a question with CloudFunctions, I need to create a function on Create of a document inside Firestore.
The problem that I have is the way the data is set up:
So I have a Collection called Chat Rooms which gets documents that will vary, and inside each document, you will have some fields and another subcollection, and inside that subcollection already the thing that I need to get on the function.
The problem that I have is that this function should be aware or access with every document created:
Somehting like:
exports.ChatSent = functions.firestore.document('chatrooms/{Variable part}/chats').onCreate((snap, ctx) => { print('do whatever'); return;});
The problem is I don't know how to write that variable part as this function should be executed whenever a new document is written on the Chats collection of each one of the documents inside the Chatroom collection.
Any Ideas?
You should use twice a wildcard when defining the path, as follows:
exports.ChatSent = functions.firestore.document('chatrooms/{chatroomId}/chats/{chatId}').onCreate((snap, ctx) => {
print('do whatever');
return null;
});
If you need to get the wildcards values, do as follows:
exports.ChatSent = functions.firestore.document('chatrooms/{chatroomId}/chats/{chatId}').onCreate((snap, ctx) => {
const chatroomId = ctx.params.chatroomId;
const chatId = ctx.params.chatId;`
print('do whatever');
return null;
});

Determine RTDB url in a trigger function

i m bulding a scalable chat app with RTDB and firestore
here is my raw structure of shards
SHARD1
Chats {
chat01: {
Info: {
// some info about this chatroom
},
Messages ...
}, ....
}
SHARD2...
now i have write triggers on all the info nodes of all the shards.
i want get the ID of the shard
How do i know what shard it actually ran on ?
[EDIT]
console.log(admin.app().name); // it prints "[DEFAULT]" in console
Puf and team please help
When a Realtime Database trigger is invoked, the second argument is an EventContext object that contains information about the database and node that was updated. That object contains a resource string, which has what you're looking for. According to the documentation for that string, it's name property will be formatted as:
projects/_/instances/<databaseInstance>/refs/<databasePath>
The databaseInstance string is what you're looking for. So, you can just split the string on "/" and take the 4th element of that array:
export const yourFunction = functions.database
.instance('yourShard')
.ref('yourNode')
.onCreate((snap, context) => {
const parts = context.resource.name.split('/')
const shard = parts[3]
console.log(shard)
})
If all you need is a reference to the location of the change, in order to perform some changes there, you can just use the ref property on the DataSnapshot that was delivered in the first argument, and build a path relative to there.

Get data from a collection with firestore ionic 4

I would like to get unique data from doc from a collection with firebase firestore
So i use to get all data:
ngOnInit() {
return this.firestore.collection('users').snapshotChanges()
.subscribe(data => {
console.log(data);
this.utilisateurs = data;
console.log(this.passided);
});
}
and this to get unique id :
this.passided = this.navParams.get('id');
And i tried to do this :
return this.firestore.collection('users').doc(this.passided).snapshotChanges()
but don't work, can you help me please?
snapshotChanges() is a method inside class AngularFirestoreCollection which returns an Observable of data as a DocumentChangeAction.
If you want to manipulate documents, then you can use the following methods:
set(data: T) - Destructively updates a document's data.
update(data: T) - Non-destructively updates a document's data.
delete() - Deletes an entire document. Does not delete any nested collections.
Therefore, this this.firestore.collection('users').doc(this.passided).snapshotChanges() wont work since snapshotChanges() is not a method in the document.ts
For reference:
https://github.com/angular/angularfire2/blob/master/docs/firestore/documents.md#snapshotchanges
https://github.com/angular/angularfire2/blob/master/src/firestore/collection/collection.ts#L97

cloud function trigger on create document

I need to create a firebase cloud function that will trigger every time I added a document to the collection. This the function:
exports.sendEmailConfirmation = functions.firestore.document('multies/{id}/tenties/{id}').onCreate((snap, context) => {
// Get an object representing the document
//...
return transporter.sendMail(mailOptions).catch((err) => {
console.error(err);
return {
error: err
}
});
});
I'm getting the following error in the console:
functions[sendEmailConfirmation(us-central1)]: Deployment error.
Failed to configure trigger providers/cloud.firestore/eventTypes/document.create#firestore.googleapis.com (gcf.us-central1.sendEmailApplicationConfirmation)
In the Firestore database I have a collection 'multies' that have multiple documents and foreach document I have a 'tenties' collection that could have multiple documents too. My function should trigger every time we add a document to the 'tenties' collection in any document in the 'multies' collection.
Can I get any help on how I'm configuring the path or what other error I'm having here?
I think you shouldn't have duplicated wildcards in your path:
try 'multies/{multiId}/tenties/{tentiId}' instead of 'multies/{id}/tenties/{id}'
Keep in mind that they will be available in your context.params object.

Resources