Get data from subcollection in firestore flutter - firebase

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

Related

Retrieve data from Flutter Firebase database

I am trying to retrieve data of all the users of the users collection and compare it with some other data. I am able to retrieve data of a particular user from its uid but want to iterate through all the collections and documents.
If you don't specify a specific document ID and use the get() method on a CollectionReference, it'll return a QuerySnapshot (containing all documents in that collection) which essentially is an array of QueryDocumentSnapshot.
FirebaseFirestore.instance
.collection('users')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
print(doc["field_name"]);
});
});
You can use "QuerySnapshot" to retrieve data of all the users of the users collection. Please see an example of same at https://firebase.flutter.dev/docs/firestore/usage/#document--query-snapshots
I expect you are currently using "DocumentSnapshot" to retrieve data of a particular user.

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 and Firebase - Get Specific Documents From Firebase

When you go into posts collection there are documents based on userId. And inside a document there is a new collection named userPosts. Inside userposts you can find postId and the details about the post.
I can get specific user post by using this code
postRef = Firestore.instance.collection('posts');
QuerySnapshot snapshot = await postRef
.document(userId)
.collection('userPosts')
.getDocuments();
But I want to get all the user posts without naming a specific user. How could I achieve this?
You can use a collection group query to query documents among all collections with same name.
QuerySnapshot snapshot = await Firestore.instance
.collectionGroup('userPosts')
.getDocuments();

how do I check collection exists or not in firestore on flutter?

I get some data from firestore. Sometimes when I called to get data, the collection is not created yet.
before calling get request, how do I check collection is exists or not?
Stream<List<ChatModel>> getChat(ChatFieldModel model) {
var ref = _db.collection('chats');
return ref
.document(model.docId)
.collection('messages')
.orderBy('timestamp', descending: true)
.snapshots()
.map((list) =>
list.documents.map((doc)=>ChatModel.fromForestore(doc)).toList());
}
I posted this before
final snapshot = await firestore.collection(roomName).getDocuments();
if (snapshot.documents.length == 0) {
//doesnt exist
}
Hope this helps
Collections are not created or deleted independently of documents. When you create a document and specify it as being part of a certain collection, that collection is created automatically if it does not already exist. Similarly, when you remove the last document in a collection, that collection will automatically be deleted. So there is really no circumstance where you need to worry about whether a collection has been created or not, and you have no explicit control over creating or deleting collections.
Usually a collection in Firestore gets deleted if no Documents exist in it.
However, there might be cases where you want to keep a history of the collection modification events, or let's say for some reason prevent Collections from being deleted.
Or for example, you want to know when a collection was created in the first place. Normally, if the Documents are deleted, and then the Collection gets created again, you will not know the initial creation date.
A workaround I can think of is the following:
Initialize each collection you want with a Document that will be specifically for keeping generic info about that collection.
For example:
This way, even if all other Documents in the Collection are deleted, you'll still keep the Collection in addition to some info that might be handy if In the future you need to get some history info about the Collection.
So to know if a Collection exists of no, you can run a query that checks for a field in Info Documents (eg CollectionInfo.exists) to know which Collections have been already created.
This is for the most recent update
final snapshot = await FirebaseFirestore.instance
.collection('collection name').get();
if ( snapshot.size == 0 ) {
print('it does not exist');
}
Feb 2022
Get QuerySnapshot and return querySnapshot.docs.isNotEmpty or isEmpty
Future<bool> isItems() async {
CollectionReference collectionReference =
_firestore.collection("users").doc(_user!.uid).collection("cart");
QuerySnapshot querySnapshot = await collectionReference.get();
return querySnapshot.docs.isNotEmpty;
}
await FirebaseFirestore.instance
.collection('collectionName')
.limit(1)
.get()
.then((snapshot) {
if (snapshot.size == 0) {
print("No collection");
}
});

How to monitor entire subcollection using transaction?

Follow this answer I am try to implement using transaction to monitor entire Firestore subcollection for new document added. Basically I only want write new document to subcollection if there is only one document. I need use transaction to avoid race condition resulting in >2 document in subcollection. Max should be 2.
How to use transaction to monitor document added to subcollection?
I am try long time to do but cannot solve.
I am experiment use iterate through subcollection for document but not know how to do this through transaction.
My code so far (maybe wrong method):
Firestore.instance.runTransaction((transaction) async {
final CollectionReference collectionRef = ref
.document(‘document’).collection(‘subCollection’);
List<DocumentSnapshot> subCollectionDocsSnapshot = [];
await collectionRef.getDocuments().then((querySnapshot) =>
querySnapshot.documents.forEach((document) {
subCollectionDocsSnapshot.add(document);
}
));
final DocumentReference newDocRef = collectionRef.document(docName);
await transaction.set(
newDocRef,
{‘docName’: docName,
}
);
});
How to solve?
Thanks!
UPDATE:
I have try add also transaction.get() to iterate through subcollection docs but it have no effect on race condition:
subCollectionDocsSnapshot.forEach((document) {
transaction.get(document.reference);
});
This isn't supported by Firestore transactions. Within a transaction, you can only find a document by its ID. You can't transact on the entire contents of a collection, and have that transaction retry if an new document is added while in the middle of the transaction. You also can't transact on the results of a query.
Instead, consider having a different document in another collection that counts the number of documents in a collection, and use that in your transaction. Or, at the very least, a document that records a boolean indicating whether or not the collection has >2 documents.

Resources