How to get data from nested collection in Flutter firestore? - flutter

I am using provider and Stream to fetch data from Firestore. so now i want to access the inner collection. but i am not able to fetch the data. How can i access myOrders collection.
this is the structure of firestore.
i tried this code to fetch but not worked for me.
//Store data into myOrders collection
Future myOrders(String image, String price) async {
final FirebaseUser user = await _auth.currentUser();
return await userData
.document(user.uid)
.collection('myOrders')
.document()
.setData({
'orderedImage': image,
'orderedPrice': price,
});
}
// get the data as snapshot
List<OrderedModel> myOrderSnapShot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return OrderedModel(
orderedImage: doc.data['orderedImage'] ?? '',
orderedPrice: doc.data['orderedPrice']);
}).toList();
}
// get the snapshot as stream
Stream<List<OrderedModel>> get orderedStream {
return userData.document(uid).collection('myOrders').snapshots().map(myOrderSnapShot);
}```

did you try printing the values and debug the code?

Related

How to read Firestore field value in flutter?

I want to get field value.
my code is..
void _checkNumner(String number) async {
final userRef = firestore.collection('users');
var documentSnapshot =
await userRef.where("number", isEqualTo: true).get().then((num) {
QuerySnapshot<Map<String, dynamic>> number = num;
print(number);
print("test");
});
print(documentSnapshot);
}
but my console is
how I get field number?
I want to load number values ​​in all docs.
I'm so beginer. T.T
Please reply from the masters
Thank you
Firebase firestore is a NoSQL, document-oriented database. User Data is stored in documents which are organized into collection , i.e collection contains list of document. In simpler words we can say QuerySnapshot contains/provide group of DocumentSnapshot. more about firestore data model
Collection --> QuerySnapshot --> Group of DocumentSnapshot
Document --> DocumentSnapshot
1) Fetch from collection - QuerySnapshot
Here we'll get list of DocumentSnapshots, we can filter by using where commad
Future<void> checkNumber(int number) async {
final QuerySnapshot snapshot = await FirebaseFirestore.instance
.collection('users')
.where("number", isEqualTo: number)
.get();
snapshot.docs.isEmpty
? {
//TODO: your code here
debugPrint("no data found")
}
: {
for (DocumentSnapshot element in snapshot.docs)
{
//TODO: your code here
debugPrint("number is: ${element['number']}"),
debugPrint("name is: ${element['name']}"),
}
};
}
1) Fetch from document - DocumentSnapshot
To fetch data from document we require documentId, and we get a single documentSnapshot instead of multiple like in above way.
Future<void> checkNumberWithDocId() async {
const String docId = 'aaaa';
final DocumentSnapshot snapshot = await FirebaseFirestore.instance.collection('users').doc(docId).get();
snapshot.exists
? {
//TODO: your code here
debugPrint("no data found")
}
: {
//TODO: your code here
debugPrint("number is: ${snapshot['number']}"),
debugPrint("name is: ${snapshot['name']}"),
};
}

Flutter - Stream not returning data

I have a document collection called posts_favorites, which stores the reference to all the Posts that a user has bookmarked. The posts_favorites collection look as follows:
I have created a Stream to get all posts references that belong to a specific user, then I want to get the Post documents from the posts collection using the posts references.
I created a Stream to produce the data I need, but I am not getting any data returned from my Stream. Here is my code for the Stream:
Stream<List<PostsRecord>> getFavoritePostsStream() async* {
List<PostsRecord> myList = [];
await FirebaseFirestore.instance
.collection("posts_favorites")
.where("user", isEqualTo: currentUserReference)
.get()
.then((favoriteList) {
favoriteList.docs.forEach((element) async {
String documentPath = element['post'].toString();
var start = documentPath.indexOf("/");
var end = documentPath.indexOf(")");
var documentRef = documentPath.substring(start+1, end);
//DocumentReference docRef = FirebaseFirestore.instance.doc(documentPath);
DocumentReference docRef = FirebaseFirestore.instance.collection('posts').doc(documentRef);
await docRef.get().then((DocumentSnapshot documentSnapshot) async {
if (documentSnapshot.exists) {
print('Document exists on the database');
PostsRecord postsRecord = PostsRecord.getDocumentFromData(
documentSnapshot.data(), element['post']);
//return myList.add(postsRecord);
//print(postsRecord);
return postsRecord;
}
});
});
});
}
I know this function works because the commented code produces the Post Records that I expect to get from Firestore.
I am not sure how to get the Stream function to return data that I can use in the Stream.
Thank you

Get value from one future and use it in another future, with Flutter

I have a favourites collection saved under a users collection. Each of the favourite documents has one field which contains a product_Id. I want to retrieve this product_id value and use it to query another collection. This second collection holds the actual products documents.
Retrieving all the documents in the favourite collection. What do I do next to get the value of the product_id fields as strings?
getIdsfromUserFavs(userId) async {
var _favData = await _usersCollectionReference
.doc(userId)
.collection('favourites')
.get();
}
This is the second method that is used to query the products collection. This method needs the String value from above in order to successfully make the query.
Future<QuerySnapshot<Object?>> queryFavsCollection(value) async {
var _favedProducts = await _productsCollectionReference
.where('prod_id', isEqualTo: value)
.get();
print(value);
return _favedProducts;
}
I am using a futureBuilder in the UI.
THis is one way I have tried(The problem with this is that I don't get any data returned):
getIdsfromUserFavs(userId) async {
var _favData = await _usersCollectionReference
.doc(userId)
.collection('favourites')
.get();
var allData = _favData.docs.map((doc) => doc.data()).toList();
allData.forEach((element) async {
String value = element['prod_id'];
print(value);
await queryFavsCollection(value);
});
}
Future<QuerySnapshot<Object?>> queryFavsCollection(value) async {
var _favedProducts = await _productsCollectionReference
.where('prod_id', isEqualTo: value)
.get();
print(value);
return _favedProducts;
}
I can see that the above methods print the ids to the console. But the FutureBuilder doesn't receive any data:
I/flutter ( 4628): 3nHHEWuCDXvbhYfT8ljY
I/flutter ( 4628): MptYFV1oXhflDYkdQyIP
I/flutter ( 4628): Fd2ntXyNVmjn0D6mG3RA
Below function will return all data from favourite collection
Future<QuerySnapshot<Map<String, dynamic>>> getIdsfromUserFavs(userId) async {
QuerySnapshot<Map<String, dynamic>> _favData = await _usersCollectionReference
.doc(userId)
.collection('favourites')
.get();
return _favData; // This will return all data of favourite collection
}
After that you can return List of desire data as shown in below function
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> queryFavsCollection(userId) async {
// Will store data in this list so at the end we can return this
List<QueryDocumentSnapshot<Map<String, dynamic>>> favData = [];
QuerySnapshot<Map<String, dynamic>> _favData =
await getIdsfromUserFavs(userId);
for (QueryDocumentSnapshot<Map<String, dynamic>> data in _favData.docs) {
String value = data['prod_id'];
QuerySnapshot<Map<String, dynamic>> _fav = await
_productsCollectionReference
.where('prod_id', isEqualTo: value)
.get();
if (_fav.docs.isNotEmpty) {
_fav.docs.forEach((element) {
favData.add(element);
});
}
}
return favData;
}
Now you can use FutureBuilder as shown below
FutureBuilder<List<QueryDocumentSnapshot<Map<String, dynamic>>>>(
future: queryFavsCollection(userId),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text('Loading...');
}
return Text('you data');
},
);
For better practice kindly refer this. This is from flutter documentation
"The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted."

Firestore how to save data in a subcollection

I have a collection users where every user has his own document. Now I want to create a subcollection to store more data related to a specific user.
So far my Code looks like this:
class DatabaseService {
Future isUserRegistered(String uid) async{
return await FirebaseFirestore.instance.collection('users')
.where('uid', isEqualTo: uid)
.get();
}
Future registerNewUser(email, password, uid) async{
return await FirebaseFirestore.instance.collection('users')
.doc(uid).set(
{
"email": email,
"password": password,
"uid": uid,
"token": -1,
"userGoal": false,
"userGender": false,
},
);
}
Future saveToRemote() async{
Map<String, dynamic> data = UserManager.userdata;
return await FirebaseFirestore.instance.collection('users')
.doc(data['uid'])
.set(data);
}
class UserManager {
static Map<String, dynamic> userdata = null;
}
How can I store data in a subcollection?
EDIT
I created a new save function but instead of storing data in a subcollection in the document with the current uid, firestore creates a new document named 'uid'. How to fix that?
Future saveInSubcollectionToRemote() async{
Map<String, dynamic> data = UserManager.userWeights;
return await FirebaseFirestore.instance.collection('users')
.doc('uid')
.collection('weights')
.doc(data['userWeight'])
.set(data);
}
Saving to a subcollection is no different from saving to a top-level collection. You build a path to the CollectionReference under the user's document and call add like this:
FirebaseFirestore.instance
.collection('users').doc(uid)
.collection('subcollection').add(
{
"field": value,
},
);

How to fetch data from Firestore and display them in Flutter?

I'm a beginner in Flutter and firestore. I have a collection in firestore with following order:
event->'a user specific id'->post->'a post id->'post details'. you can see hereFirestore1 and hereFirestore2
When I try to fetch the 'postdetails', only thing I get is 'Instance of 'DocumentSnapshot',see hereResponse
What i tried:
getEvents() async {
setState(() {
_isLoading = true;
});
DocumentSnapshot snapshot = await eventref
.doc(uid)
.collection('post')
//.orderBy('Date', descending: true)
.doc()
.get();
print('Snapshot : ${snapshot}');
return snapshot;
// setState(() {
// _isLoading = false;
// print(event);
// });
}
I have also made a model for events. See hereEvent Model
I want to fetch data and display them as card.
Any help?
Thanks in Advance
print('Snapshot : ${snapshot.data()["Date"]}');
Using data() you can access the fields value.
snapshot.get("field_name")
You need to ask flutter to retrieve the fields inside the document snapshot.
Will need a more detailed order of your firestore collection and document to provide the exact code. You may follow the sample below:
On firestore:
-Collection: "users"
---Document: "userId"
-------Field: "username"
-------Field: "birthdate"
Code:
DocumentSnapshot doc =await _firestore.collection("users").doc(userId).get();
print(doc.get('username'));
print(doc.get('birthdate'));