How to add Firestore data into List<List> - flutter

I want to add Firestore data into List to display it in a pdf report, this way wouldn't work properly I mean they not show the data in the list and display some error I don't know what the problem?
Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform"
theData() async {
await FirebaseFirestore.instance
.collection('QFS')
.snapshots()
.forEach((QuerySnapshot snapshot) {
for (int index = 0; index < snapshot.docs.length; index++) {
List<List> listOfData = [];
listOfData
.add({snapshot.docs[index]["commodity"]}.toList());
print(listOfData);
}
});
}

I think you should try optimising your code using forEach() loop instead of for() loop and you should try using docs[index].get(‘commodity’) instead of docs[index][“commodity”].
You can refer to these stackoverflow links for more insight: Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform, How to fix Bad state: field does not exist within the DocumentSnapshotPlatform.

Related

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

DocumentID search in Firestore with a List

Can i search a Firestore DocumentID with a List<String>?
I am trying to search through my collection with some selection of documentID in a List. The List will consist of few String. Can I search through the Firestore collection using this?
This is the List:
List<String> _selectedBusStop = List<String>();
This is the code I used in finding the DocumentID based on the list that is in here.
Future <void> saveRoute(_selectedBusStop) async{
Firestore.instance.collection('markers').where('BusstopName', isEqualTo: _selectedBusStop)
.snapshots().listen((location) {
if(location.documents.isNotEmpty){
for (int i = 0; i < location.documents.length; i++){
initRoute(location.documents[i].data, location.documents[i]);
}
}
});
setState(() {
});
}
I am using where and isEqualTo or is this approach wrong? Any idea how to make it work for this part? Thank you in advance for your help.
Update:
This is how my Firestore looks like:
The List have some of the BusstopName but not all of it. I do not want to retrieve all the data from the Firestore just the one that is in the List. Sorry for causing so many misunderstanding.
Use the whereIn operator, like this:
Future <void> saveRoute(_selectedBusStop) async{
Firestore.instance.collection('markers').where('BusstopName', whereIn: _selectedBusStop)
.snapshots().listen((location) {
if(location.documents.isNotEmpty){
for (int i = 0; i < location.documents.length; i++){
initRoute(location.documents[i].data, location.documents[i]);
}
}
});
setState(() {
});
}
Assuming your documents have a unique id stored in the field BusstopName and also the documents actual id matches the content of this field, you have 2 possibilities.
(1) .where query
query data with collection("markers").where("BusstopName", "=", "yourBuststopId").
this returns a querySnapshot Object, on which you can call .size to check if there were any documents with that Id found (could be more than 1 if you have an inconsistent database).
(2) .doc query
query data with collection("markers").doc("yourBuststopId")
this returns a documentSnapshot Object, on which you can call .exist to check if the document actually exsists.
In both cases you need to do 1 query per Id, because Firestore queries only support equality and range operations. See this similar SO question. I would suggest to do the queries asynchronously, otherwise the time to execute will increase with the size of the array.
If you are concerned about costs, you only get billed for the results that actually return documents that exist.
you might also try this:
FirebaseFirestore.instance
.collection('markers')
.where('BusstopName', arrayContainsAny: ['Utar Bus Stop', 'Garden Bus Stop'])
.get()
.then(...);
Taken from the examples documentation

Get all documents from a Firestore collection in Flutter

I tried with different ways but i can't edit the structure of code
//First way
QuerySnapshot querySnapshot = await db.firestoreInstance.collection('user-history').get();
var list = querySnapshot.docs;
print('MY LIST ===== $list');
//Second way
final CollectionReference collectionRef = db.firestoreInstance
.collection(historyCollection);
print('MY SECOND LIST ===== $list');
collectionRef.get().then((qs) {
qs.docs.forEach((element) {
print('MY doc id ${element.id}');
});
});
In my firebase collection(historyCollection) i have four documents but the debugger returns me empty array []. Is there another way to call all documents in certain collection through flutter?
I'm trying to call this method through FutureBuilder component.
My version of firestore is: "cloud_firestore: ^0.16.0+1"
This should do the trick:
Future<List<dynamic>> getCollection(CollectionReference collection) async {
try {
QuerySnapshot snapshot = await collection.get();
List<dynamic> result = snapshot.docs.map((doc) => doc.data()).toList();
return result;
} catch (error) {
print(error);
return null;
}
}
The entire problem was not from these fragments of code. This problem is came out from this that my collections have subcollections. I read about this and i understand that subcollections can live without their ancestors and the only way to access parents is to do this is directly specify the exact path and name of the document. To work this code in my case was needed to add dummy components of my entire set of collections. For more information please look up these two topics:
-> https://firebase.google.com/docs/firestore/using-console
-> Firestore DB - documents shown in italics

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

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.

Firestore asks me create the index that is already exist

I'm trying to paginate comments. The first 10 comments is loading ok, but next ones (when query contains startAfterDocument) return error like:
Query(comments where movie_id == 1041047 order by -created, __name__) failed: Status{code=FAILED_PRECONDITION, description=The query requires an index. You can create it here: https://console.firebase.google.com/project/.......
But this index is already exist, I created it before. And if I follow the suggestion link Firebase Console tells me the same: this index is exist.
Future<List<DocumentSnapshot>> _loadPageFrom(
int index, DocumentSnapshot lastDoc) async {
Query query = Firestore.instance
.collection('comments')
.where('movie_id', isEqualTo: movieID)
.orderBy('created', descending: true);
if (lastDoc != null) query = query.startAfterDocument(lastDoc);
final snapshot = await query.limit(10).getDocuments();
return snapshot.documents;
}
What problem is here?
If you had recently deleted your index, you will need to wait a little bit until it's deleted from your project inside GCP, after that you will be able to create it again.