How to map sub collection to json_serializable nested class? - firebase

json_serializable supports nested classes:
https://docs.flutter.dev/development/data-and-backend/json#generating-code-for-nested-classes
My goal is to have a Parent class with a Child member, and I want the firestore to look like:
Collection(Parent) -> {parentId} -> Collection(Child) -> {childId}
What is not clear is how the firestore that backs this model is supposed to be structured and accessed.
Any ideas? Thank you

This could help https://firebase.flutter.dev/docs/firestore-odm/subcollections/ but it's not ready for production.
In the meantime, I'd create instances (with json_serializable) programmatically, like:
QuerySnapshot subCollQuerySnapshot = await FirebaseFirestore.instance
.collection("maincoll") //
.doc(mainDoc.id) //
.collection("subcoll") //
.get();
for (var subCollDoc in subCollQuerySnapshot.docs) {
MySubCollClass mySubCollInstance = MySubCollClass.fromJson(subCollDoc.data());
// ... add mySubCollInstance to your mainInstance's list
}

Related

Flutter Firestore - How to get data from a Document Reference in a Document Field?

I'm building a Self-learning app with differente questions types. Right now, one of the questions have a field containing a list of DocumentReferences:
In Flutter, I have the following code:
Query<Map<String, dynamic>> questionsRef = firestore
.collection('questions')
.where('lesson_id', isEqualTo: lessonId);
await questionsRef.get().then((snapshot) {
snapshot.docs.forEach((document) {
var questionTemp;
switch (document.data()['question_type']) {
....
case 'cards':
questionTemp = CardsQuestionModel.fromJson(document.data());
break;
....
}
questionTemp.id = document.id;
questions.add(questionTemp);
});
});
Now, with "questionTemp" I can access all the fields (lesson_id,options,question_type, etc..), but when it comes to the "cards" field, how Can I access the data from that document reference?
Is there a way to tell firestore.instance to get the data from those references automatically? Or do I need to make a new call for each one? and, if so, how can I do that?
Thank you for your support in advance!
Is there a way to tell firestore.instance to get the data from those
references automatically? Or do I need to make a new call for each
one?
No there isn't any way to get these documents automatically. You need to build, for each array element, the corresponding DocumentReference and fetch the document.
To build the reference, use the doc() method
DocumentReference docRef = FirebaseFirestore.instance.doc("cards/WzU...");
and then use the get() method on this DocumentReference.
docRef
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('Document exists on the database');
}
});
Concretely, you can loop over the cards Array and pass all the Futures returned by the get() method to the wait() method which "waits for multiple futures to complete and collects their results". See this SO answer for more details and also note that "the value of the returned future will be a list of all the values that were produced in the order that the futures are provided by iterating futures."

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;
});

Put only existing subcollection in a list firebase(flutter)

I've been trying to put document snapshots of a sub-collection in a list. The code for it is something like this:-
getcoffeebuyerlist() async {
DocumentSnapshot coffeebuyers;
List<DocumentSnapshot> finalCoffeBuyerList = [];
for (var i = 0; i < profiles.length; i++) {
coffeebuyers = await Firestore.instance
.collection('profileData')
.document(profiles[i].uid)
.collection('coffeeprices')
.document(profiles[i].uid)
.get();
finalCoffeBuyerList.add(coffeebuyers);
}
return finalCoffeBuyerList;
}
There are two profile and only one of which has a sub-collection 'coffeeprices'.
My doubt here is by trying get snapshot of sub-collections, will I automatically be creating an empty document for the second profile for which sub-collection doesn't exist and put in finalCoffeBuyerList list?
Or only those(one in my case) sub-collection which already exist are added to this list?
Your code here will never create any documents. get() doesn't create a document if the document doesn't already exist. You should check the returned DocumentSnapshot to see if the document actually exists. Something like this:
if (coffeebuyers.exists) {
finalCoffeBuyerList.add(coffeebuyers);
}
The only way to create a document is with add() or set().

Firebase Firstore subcollection

please how can I get all the value of my IndividualTaxData subcollection in Flutter.
First, you must get the reference to the parent document:
DocumentReference parentRef = Firestore.intances.collection('TaxData').document(taxDataId);
You can do the previous part with a direct reference to the document (like the code above) or with a query. Later, you must get the reference of the subcollection and the document that you get the information:
DocumentReference subRef = parentRef.collection('IndividualTaxData').document(individualTaxId);
And finally, get the data:
DocumentSnapshot docSnap = await subRef.get();
For you to return a simple document, you can use the following code for it.
var document = await Firestore.instance.collection('IndividualTaxData').document('<document_name>');
document.get() => then(function(document) {
print(document('character'));
// you can print other fields from your document
}
With the above code, you will reference your collection IndividualTaxData and then load it's data to a variable that you can print the values.
In case you want to retrieve all the documents from your collection, you can start using the below code.
final QuerySnapshot result = await Firestore.instance.collection('IndividualTaxData').getDocuments();
final List<DocumentSnapshot> documents = result.documents;
documents.forEach((data) => print(data));
// This print is just an example of it.
With this, you will load all your documents into a list that you iterate and print after - or that you can use with another method.
In addition to that, as future references, I would recommend you to check the following links as well.
Query a single document from Firestore in Flutter (cloud_firestore Plugin)
How to use Cloud Firestore with Flutter
Le me know if the information helped you!

Firestore: Getting a subcollection from a DocumentSnapshot

I'm using Firestore for backend for a Flutter project, and the database is nested to have sub-collections under documents.Here's the structure:
I have the data found from the Root collection, and from there I'm trying to get the sub-collection, but I can't figure how to.
There should be a get() method available but I'm not getting any.
Here's the code for the function:
void _getNext(DocumentSnapshot doc) async {
int v = doc.data.length;
String id = doc.documentID;
print('length = $v \t id= $id');
await doc.reference.get().then((val){
val.data.forEach((k, v){
print('k = $k & v = $v');
});
});
await doc.data.forEach((k,v){
print("new k = $k, v = $v");
});
await doc.reference.collection(id).getDocuments().then((val){
val.documents.forEach((e){
print("another k = $e");
});
});
}
And the only response I get from pressing the "Literature" document (from the root collection) is this:
I/flutter (13395): length = 0 id= Literature
There are several sub collections to this document but the returned length is zero. The other blocks of code work fine when I added dummy data to the fields, but that's not needed in my case.
Thank You for your help.
collection() returns a CollectionReference. As you can see from the API docs, neither CollectionReference, nor it superclass Query have a method called get(). I suspect you want to use getDocuments() instead.
There is no get() method for CollectionReference, you need a DocumentReference.
There is nothing wrong with the current situation, you probably want to use getDocuments() since there are no subcollections under your collection, but documents
Notice the alternating pattern of collections and documents. Your collections and documents must always follow this pattern. You cannot reference a collection in a collection or a document in a document.
from: Hierarchical Data

Resources