How to print values from array field from Firestore? - flutter

I have the following courses array in Firestore:
How can I print all the items in Courses array?
I have the following code which currently just fetches the data from Firestore:
printAllValuesFromArray() {
var courses = FirebaseFirestore.instance
.collection('CurrentCourses')
.doc(user.uid)
.get()
.then((value) {
return value['courses'];
});
}

You are correctly fetching the document of the user, all you need is to just print the value like the following:
Future<void> printAllValuesFromArray() {
return FirebaseFirestore.instance
.collection('CurrentCourses')
.doc(user.uid)
.get()
.then((document) {
final courses = document['Courses'];
for (var course in courses) {
print(course);
}
});
}
Note: You were using incorrect key to access the courses from the document which was courses while the correct one is Courses with capital C,

value['courses'].forEach((val) {
print(val);
});
// Can you try this

You can try this,
printallvaluesfromarray() {
var courses = FirebaseFirestore.instance
.collection('CurrentCourses')
.doc(user.uid)
.get()
.then((value) {
print(value.toString())
return value['courses'];
});
}

Related

How to use Array contains in the same array fields in firebase for flutter

I have a chat collection.
each document has an array with two user id's.
my goal is to get the chat that has both user sys id's
I tried running the following but I got an error because we cant use two 'arrayContains' in one query.
Is there any way to perform such query?
here is an image of the data structure
Future getChat({required List userIdsArr}) async {
var docId = '';
userIdsArr.sort((a, b) {
return a.compareTo(b);
});
var filter1 = userIdsArr[0];
var filter2 = userIdsArr[1];
await chat
.where(userIdsArrayColumn, arrayContains: userIdsArr[0])
.where(userIdsArrayColumn, arrayContains: userIdsArr[1])
.get()
.then((value) {
value.docs.forEach((element) {
docId = element.id;
});
});
return docId;
}
the goal is to get the chat that pertains to the users being passed in userIdsArr
this seems to work, is there a better way of doing this?
Future getChat({required List userIdsArr}) async {
var docId = '';
userIdsArr.sort((a, b) {
return a.compareTo(b);
});
await chat
.where(userIdsArrayColumn, arrayContains: userIdsArr[0])
// .where(userIdsArrayColumn, arrayContains: userIdsArr[1])
.get()
.then((value) {
value.docs.forEach((element) {
if (element[userIdsArrayColumn].contains(userIdsArr[1])) {
log('match found!');
docId = element.id;
}
});
});
return docId;
}
A query can only contain a single array-contains query.
To allow your query, you'll want to add an additional field to the document where you keep the pair of UIDs in a predictable (e.g. alphabetical) order. With such a field you can then use a query such as:
where("concatenated_uids", isEqualTo: userIdsArr[0]+"_"+ userIdsArr[1])

How to loop through a DocumentSnapshot.data and retrieve id's and keys?

How do I loop through a DocumentSnapshot.data() object and retrieve its keys and values?
My code currently looks like this:
Future<void> drawPolygons() async {
var points = await FirebaseFirestore.instance
.collection('polygons')
.doc(uid)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
//if user has polygon data on account
var data = documentSnapshot.data();
}
});
}
**Update Your Method and Convert the data to Map**
Future<void> drawPolygons() async {
var points = await FirebaseFirestore.instance
.collection('polygons')
.doc(uid)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
Map data = (documentSnapshot.data() as Map);
for (var entry in data.values) {
print(entry);
}
}
});
}

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']}"),
};
}

How to get a subcollection from a document firestore flutter

Im trying to fetch the documents from a subcollection which is in another document, and when I try to fetch the docs and fill a local list with the "docs data" it doesn't fill it, can anyone tell me what I'm doing wrong here?
My method of when I try to fetch the subcollection:
static Stream<List<CheckInOutModel>> employeeCheckInOutStream() {
return firebaseFirestore
.collection('employees')
.doc(auth.currentUser!.uid)
.collection('employeeList')
.snapshots()
.asyncMap((QuerySnapshot querySnapshot) {
final List<CheckInOutModel> employeesCheckInOutList = [];
for (final element in querySnapshot.docs) {
firebaseFirestore
.collection('employees')
.doc(auth.currentUser!.uid)
.collection('employeeList')
.doc(element.id)
.collection('checkInOutList')
.snapshots()
.asyncMap((QuerySnapshot query) {
for (final element in query.docs) {
final employeeCheckInOutModel =
CheckInOutModel.fromDocumentSnapshot(
documentSnapshot: element,
);
employeesCheckInOutList.add(employeeCheckInOutModel);
}
});
}
return employeesCheckInOutList;
});
}
My method when I fetch the fields of the documents that the subcollection is in:
static Stream<List<EmployeeModel>> employeeStream() {
return firebaseFirestore
.collection('employees')
.doc(auth.currentUser!.uid)
.collection('employeeList')
.snapshots()
.map((QuerySnapshot query) {
final List<EmployeeModel> employees = [];
for (final employee in query.docs) {
final employeeModel =
EmployeeModel.fromDocumentSnapshot(documentSnapshot: employee);
employees.add(employeeModel);
}
return employees;
});
}
So I figured out what I did wrong here, I tried to call a stream of it when I only needed it when a callBack is called, so I changed the logic accordingly and went with Future instead Stream
My updated code:
static Future<List<CheckInOutModel>> employeeCheckInOutStream({
required String id,
}) async {
final List<CheckInOutModel> employeesCheckInOutList = [];
final query = await firebaseFirestore
.collection('employees')
.doc(auth.currentUser!.uid)
.collection('employeeList')
.doc(id)
.collection('checkInOutList')
.get();
for (final employee in query.docs) {
final employeeCheckInOutModel = CheckInOutModel.fromDocumentSnapshot(
documentSnapshot: employee,
);
employeesCheckInOutList.add(employeeCheckInOutModel);
}
return employeesCheckInOutList;
}

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