how to retrieve unknown sub collection from document in flutter - firebase

I have the following code with the objective of retring all the documents like this: Collection('A').document(currentUser), this should give me the document YRZ1**** as you may see in the first image. Now what I want to do is get all the documents in the t22o9*** subcollection, as showned on the second image, how can I do that?
var docPath=Firestore.instance.document('Messages/$currentUser');
docPath.snapshots().listen((event) {
print('Hello 12 ${event.data}');
});

In order to get data from subcollection you can do the following:
var db = Firestore.instance;
//This is a reference to the YRZ1**** doc
var messagesDoc = db.collection('Messages').document('Messages/$currentUser');
//collectionId is the t22o9*** id, you need to have this set previosly in your code
var docList = [];
messagesDoc.collection(collectionId)
.getDocuments()
.then((QuerySnapshot snapshot) {
snapshot.documents.forEach((doc) => docList.add(doc)'));
});
With this code, docList will be a list of the documents located at your subcollection t22o9*** of the YRZ1*** document.
Also you can check this link with some examples on how to get data from firestore using flutter.
EDIT:
As per what you have clarified on the comments, getting the subcollection data is a bit more complicated with subcollections that were created dynamically, as you can see on this link, which I assume is the case you have. The most feasible solution in your case would be to create a list of ids of subcollections in your parent document, so for example your YRZ1*** document would have this structure
document
id: YRZ1***
subCollectionIds : [subCollectionId1, subCollectionId2,...]
subCollection1
subCollection2
...
subCollectionN
Having this structure you could use this code to retrieve the list of subcollections and the first document of each subcollection, ordered by whatever field you'd like:
var db = Firestore.instance;
var listFirstDocSub = []
//This is a reference to the YRZ1**** doc
db.collection('Messages')
.document('Messages/$currentUser')
.getDocument()
.then((DocumentSnapshot doc) {
var listSubCollections = doc["subCollectionIds"];
listSubCollections.forEach((id) {
db.collection('Messages')
.document('Messages/$currentUser')
.collection(id)
.orderBy("WHATEVER_FIELD_YOU_DECIDE")
.limit(1)
.getDocuments()
.then((DocumentSnapshot snapshot) {
listFirstDocSub.add(snapshot);
})
});
});
NOTE: With this approach, everytime you add a new subcollection, you will also need to add it's id to the subCollectionIds list.
Hope This helps.

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."

Get data from subcollection in firestore flutter

In the 1st screen shot there are many documents in collection users. Each documents contains further collection jobPost and that collection contains further documents and its meta data.
What I want here is go to the every document of collection users and further subcollection jobPost and fetch all the documents.
Suppose first it should go to document 1 in collection users, in the document 1 it should fetch all the documnets in subcollection jobPost then it should go to the 2nd document of collection users and then get all the documents in the subcollection jobPost and so on. what will be the query or implementation to this technique
What you're describing is known as a collection group query, which allows you to query all collections with a specific name. Unlike what the name suggests, you can actually read all documents from all subcollections named jobPost that way with:
FirebaseFirestore.instance.collectionGroup('jobPost').get()...
When performing a query, Firestore returns either a QuerySnapshot or a DocumentSnapshot.
A QuerySnapshot is returned from a collection query and allows you to inspect the collection.
To access the documents within a QuerySnapshot, call the docs property, which returns a List containing DocumentSnapshot classes.
But subcollection data are not included in document snapshots because Firestore queries are shallow. You have to make a new query using the subcollection name to get subcollection data.
FirebaseFirestore.instance
.collection('users')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
FirebaseFirestore.instance
.document(doc.id)
.collection("jobPost")
.get()
.then(...);
});
});
**
if you not have field in first collection document then its shows italic thats means its delte by default otherwise if you have field in first collection document then you can access it easily so this is the best way that i share
**
static Future<List<PostSrc>> getAllFeedPosts()async
{
List<PostSrc> allPosts = [];
var query= await FirebaseFirestore.instance.collection("posts").get();
for(var userdoc in query.docs)
{
QuerySnapshot feed = await FirebaseFirestore.instance.collection("posts")
.doc(userdoc.id).collection("userPosts").get();
for (var postDoc in feed.docs ) {
PostSrc post = PostSrc.fromDoc(postDoc);
allPosts.add(post);
}
}
return allPosts;
}

How to read firestore collection?

How can I list all documents in a firestore
FirebaseFirestore.instance
.collection('groups')
.doc('dialog')
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('Document data: ${documentSnapshot.data()}');
} else {
print('Document does not exist on the database');
}
});
this code Always return to else
From the docs:
When you delete a document, Cloud Firestore does not automatically delete the documents within its subcollections. You can still access the subcollection documents by reference. For example, you can access the document at path /mycoll/mydoc/mysubcoll/mysubdoc even if you delete the ancestor document at /mycoll/mydoc.
Non-existent ancestor documents appear in the console, but they do not appear in query results and snapshots.
A document can exist even if one or more its ancestors don't exist. For example, the document at path /mycoll/mydoc/mysubcoll/mysubdoc can exist even if the ancestor document /mycoll/mydoc does not. The Cloud Firestore data viewer displays non-existent ancestor document as follows:
In a collection's list of documents, the document IDs of non-existent ancestor documents are italicized.
In a non-existent ancestor document's information panel, the data viewer points out that the document does not exist.
Since your document name is italicized, which means you either deleted the document or added the subcollection to an empty document which it seems you might have done according to your screenshot. Therefore to solve the issue delete the collection group and add the document with data:
FirebaseFirestore db = FirebaseFirestore.instance;
db.collection("group").doc("dialog").set({"name" : "peter"}).then((value){
db.collection("group").doc("dialog").collection("Tkxij").add({"test" :"test"});
});
Also queries are shallow, meaning if you are referencing a document then you will only get the data of that document, you won't get the data inside the subcollections.
I have added the code for your problem hope this clears your doubt, feel free to ask if you have any doubt.
getData( ) async{
final collectionData = await FirebaseFirestore.instance
.collection('groups').get();
//this forEach method will give every document of that collection
collectionData.docs.forEach((doc) {
final docData = doc.data();
final fieldData = docData['fieldName'];
});
}

Flutter Firebase How to get random document

I am trying to get some random posts from Firebase. But i am unable to get random document id.
Is there any way to retrieve data from Firebase like this :-
getRandomData() async {
QuerySnapshot snapshot = await posts
.document(random.id)
.collection('userPosts')
.getDocuments();}
i am trying to say that. Now i am able to get documentID normally not in italics.so now how can i get random documentID from Firebase.
List documentIds in a list first.
var list = ['documentId1','documentId2','documentId3'];
var element = getRandomElement(list);
Then query the documentSnapshot
You can first get all documents in you collection.
Try this code:
async getMarker() {
const snapshot = await firebase.firestore().collection('userPosts').get();
const documents = [];
snapshot.forEach(doc => {
documents[doc.id] = doc.data();
});
return documents;
}
Next, from return documents you can create a list of documents id and get random numbers (document id) from this list.
The main problem here that's going to prevent you from moving forward is the fact that you don't actually have any documents nested immediately under "posts". Notice that the names of the documents are in italics. That means there isn't actually a document here at all. The reason why they are show, however, is because you have a subcollection "userPosts" nested under the path where that document ID exists.
Since you don't have any documents at all under "posts", the usual strategies to find a random document won't work at all. You're going to have to actually populate some data there to select from, or find another way to select from the data in the subcollections.
firestore()
.collection('SOURCE')
.doc(props?.route?.params?.data?.id)
.collection('userPosts')
.get()
.then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
console.log('User ID: ', documentSnapshot.id, documentSnapshot.data());
})
})

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().

Resources