FLUTTER FIRESTORE -Query the field and get document id and check other field - flutter

am trying to get the searched value(userid) which is in the field of a document in firestore I want to check the other fields(status) of the document I tried this method but failed
handlesubmit(BuildContext context)async{
final QuerySnapshot searcheduserid=
await Firestore.instance.collection('users')
.where('userid',isEqualTo: userid).limit(1).getDocuments();
final userdocid=searcheduserid.documents.map((doc)=>doc.documentID);
final DocumentSnapshot getuserdoc= await Firestore.instance.collection('users')
.document(userdocid).get();
final userstatus = getuserdoc.data['status'];
// I GET AN ERROR HERE ERROR SAYS
// METHOD [](status) was called on null
if(userstatus==null){
return showdialog( context,'the entered user id status does not exist');
}
}

You probably copied an older version of your code because it is unlikely that your code compiles the following line of your program:
final DocumentSnapshot getuserdoc= await Firestore
.instance
.collection('users')
.document(userdocid).get();
The error message on my system is:
The argument type 'Iterable<String>' can't be assigned to the parameter type 'String'.
Which means that userdocid is an Iterable of type String (Iterable<String>), but a parameter which is of type String is expected.
You have multiple options of fixing the problem, but I suggest the following:
Since you are only expecting one document from your QuerySnapshot it is enough to just look at the first document.
final QuerySnapshot searchedUserId = await Firestore.instance
.collection('users')
.where('userid', isEqualTo: userid)
.limit(1)
.getDocuments();
// if it is possible that searchedUserId returns no document make sure to
// check whether searchedUserId.documents.length > 0,
// otherwise searchedUserId.documents.first will throw an error
DocumentSnapshot document = searchedUserId.documents.first;
final userDocId = document.documentID;
final DocumentSnapshot getuserdoc =
await Firestore.instance.collection('users').document(userDocId).get();
Improved Solution:
However I think your code is a bit redundant anyways, because you are looking up a field of a document which has the same value as the document ID. You could shorten the whole code to
final DocumentSnapshot getuserdoc =
await Firestore.instance.collection('users').document(userid).get();
Error calling getuserdoc.data['status']
If you get an error saying something similar to
[](status) was called on null
Then that means getuserdoc has no value. This is likely due to the fact that there is no such database entry with the given ID. Check if the ID is in your database, otherwise comment below for additional information, because the provided code had compilation errors and does not run at all.

Related

Why is vs code saying the method '.getDocuments' and the getter documents are not defined for types Query and QuerySnapshot respectively?

void _getQuestions() async {
// Query Firestore for questions with the specified tags
Query query = await _firestore
.collection('questions')
.where('tags', arrayContainsAny: widget.tags);
QuerySnapshot querySnapshot = await query.getDocuments();
setState(() {
_questions = querySnapshot.documents;
});
importing cloud_firestore.dart.
I expected the errors to leave, but they are still around.
The method to get the documents is called get() in Flutter, not getDocuments().
I recommend keeping the Firebase documentation handy for this sort of thing, for this case that'd be the section on getting multiple documents from a collection

Flutter firestore returns length 0 while there is data in firestore

I have the following code in flutter:
QuerySnapshot querySnapshot =
await _firestore.collection("user1#gmail.com").get();
List Data = querySnapshot.docs.map((doc) => doc.data()).toList();
print("Length: ${Data.length}");
Here is my firestore database:
I get the following output:
I/flutter (11484): Length: 0
The Documents for each user email is variable, so I need the length of the documents. Also I need to get to the details of each document like content and title. How to do it? Thanks.
Could you try this:
int size = await FirebaseFirestore.instance.collection(collectionPath).get(GetOptions(source:Source.server))..size;
I will recommend finding a way to store the length of documents as a field in your Cloud Firestore database because calling the get function on a whole collection means filling up the mobile phone memory. (Say you have 500,000 users at least). This makes your app slow
You could have a field called count such that when you add a document, you can use the firebase transaction to update firebase.
For example:
// Create a reference to the document the transaction will use
DocumentReference documentReference = FirebaseFirestore.instance
.collection('users')
.doc(documentId);
return FirebaseFirestore.instance.runTransaction((transaction) async {
// Get the document
DocumentSnapshot snapshot = await transaction.get(documentReference);
if (!snapshot.exists) {
throw Exception("User does not exist!");
}
// Update the follower count based on the current count
// Note: this could be done without a transaction
// by updating the population using FieldValue.increment()
// Perform an update on the document
transaction.update(documentReference, {'followers': FieldValue.increment(1);});
// Return the new count
return newFollowerCount;
})
.then((value) => print("Follower count updated to $value"))
.catchError((error) => print("Failed to update user followers: $error"));
You can see more documentations here: FlutterFire

FirebaseException: Not able to query a collectionGroup

I am trying to do a pretty simple query in firebase for a collectionGroup. I only want to get all the products that are of the type "Restuarant". The code is below:
QuerySnapshot res = await FirebaseFirestore.instance
.collectionGroup('products')
.where("type", isEqualTo: "Restuarant")
.get();
It keeps throwing a FirebaseException as below:
I have added an exception in the Firebase indexes. It is a single field index.
What is the issue here? Why is this Exception occurring?
So I was able to get it working by adding a composite index. After adding the composite index, I was able to perform orderBy query too, using the rating field.
QuerySnapshot res = await FirebaseFirestore.instance
.collectionGroup('products')
.where("type", isEqualTo: "Restuarant")
.orderBy("rating", descending: true)
.get();

How to update nested field inside a document in Firestore Flutter

I am working with Flutter and Cloud Firestore, and I'm stuck on the point where I need to update a nested field inside my collection -> document. Below is the screenshot of my firestore collection structure. I know how to do basic update method like FirebaseFirestore.instance.collection('collection_path').doc('data').update(...), however, in my case, the document structure is a bit complex so I need some help in case of performing update method.
Here, I need to change (on a button press) the field status to true/false under strategies array.
I have the access to strategyName field so that I could get that item in the strategies array and change it...
What I tried:
ElevatedButton(
onPressed: () async {
// status=true
final value = await FirebaseFirestore.instance
.collection(widget.symbol + '_Live')
.doc("data")
.get();
final data = value.data();
final strategies =
data!['strategies'] as List<Map<String, dynamic>>;
final strategy = strategies.firstWhere(
(item) => item['strategyName'] == strategyName,
orElse: () => Map());
strategy['status'] = true;
await FirebaseFirestore.instance
.collection(widget.symbol + '_Live')
.doc("data")
.update(data);
},
child: Text("Start"),
),
Obviously, this won't work because here I'm just changing it locally, i.e. not using the Firestore update method to actually change the field. But I'm confused as to how to update that nested field.
Any leads/help would be really appreciated!
EDIT:
I did as you told and edited my answer, but now the error is gone but nothing seems to work, i.e. in firestore, there is no change in the data doc.
ERROR: Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>' in type cast
You need to update value map locally, then store it back:
final value = await FirebaseFirestore.instance
.collection(symbol + '_Live')
.doc("data")
.get();
final data = value.data();
final strategies =
data!['strategies'].map((item) => item as Map<String, dynamic>).toList();
final strategy = strategies.firstWhere(
(item) => item['strategyName'] == strategyName,
orElse: () => Map());
strategy['status'] = toggleValue;
await FirebaseFirestore.instance
.collection(symbol + '_Live')
.doc("data")
.update(data);
The point is to store the entire value.
EDIT by Author : Just needed to map each element to Map<String, dynamic>.

CollectionReference to DocumentReference

I'm trying to perform a firestore transaction in Flutter.
Therefore I need to pass the documentReference.
There is no problem, when accessing the "lesson" document based on the identifier.
The issue is when fetching the active user pass. The where I'm trying to use returns the Query, and the .reference() returns the CollectionReference (which is not accepted by the transaction method).
How can I get the reference to the document basing on the value of its field.
To spice it up: DB rules don't allow me to read ALL the passes. I've got only access to those, that have my UserID (double checked - working).
DocumentReference lessonRef =
await _db.collection('lessons').document(lesson.identifier);
CollectionReference passRef = await _db
.collection('passes')
.where('userID', isEqualTo: user.identifier).reference();
You can get the DocumentReference of the Queried documents like so:
Firestore.instance
.collection('passes')
.where('userID', isEqualTo: user.identifier)
.snapshots()
.listen((reference) =>
data.documents.forEach((doc) => /*do what you want with doc.reference*/));
(I'm not an expert in Flutter and I could't test the code, but I based the answer in the API reference)