Firestore Flutter How Sort Data using int fields - flutter

Hello i have a firestore db with structure
Root
.....Oder
.........Xyz1
______T:1
.........Xyz1
______T:1
when i get the data i want it to sort automatically in desending oder using the int value stored in 'T'
T is unique for every document
child: StreamBuilder(
stream: Firestore.instance.collection("Oder").snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return new Text('Loading...');
}
return new ListView(
reverse: true,
children: snapshot.data.documents.map((document) {
return new ListTile(
title: new Text(document['T'].toString()),
);
}).toList(),
);
},
),
This is my code here
I also have the same value of T as String as each document name so sorting with that gave me 1,10,11,2,3...
So i need to get sorted with the int value stored in T

This is
You can get the data with this line:
CollectionReference collectionReference = Firestore.instance.collection("data-collection");
But , you can get the ordered data with:
Query collectionReference = Firestore.instance.collection("data-collection").orderBy('field');
orderBy should returns a Query, you can no longer store it as a CollectionReference.

Related

how to get document id index on firestore with flutter onTap method

I am trying to get the document ID. I don't know if it is the right way, but until now I could manage to get all the IDs.
Then I am trying to get the document ID index so I can open the category with onTap and show the category products.
I have tried with map, forEach, etc... but nothing.
return Scaffold(
body: StreamBuilder(
stream: firestore.snapshots(),
builder:(context, snapshot){
if (snapshot.connectionState == ConnectionState.waiting)
return Center(child: CircularProgressIndicator());{
final document = snapshot.data?.docs;
return ListView.builder(
itemCount: document?.length,
itemBuilder: (context, index) {
return Center(
child: Column(
children: [
InkWell(
onTap: (){
FirebaseFirestore.instance.collection('prova').get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.map((doc) {
print(doc.id);
var docId = doc.id;
Navigator.push(context, MaterialPageRoute(builder: (context)=>
CategoriesPage(document: document[index]['name'], docId: docId)));
});
});
As I mentioned in my comment, the way FireStore allows you to store data is alternating between collections and docs. That's to say you can't put another doc into a doc, and another collection within a collection. You can only put docs in a collection, and then subcollections within a doc, etc, etc.
I'm unaware of your data structuring needs, however I'd suggest something like this:
When a user creates a category, simply add it to their doc, and then any products within the category could be placed into a sub-collection under that category. Let me know if that could work for you.

Retrieve from Firestore just the UserID in the array Flutter

Hello I have a stream Builder in firestore which display a list of user.
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('Users').where('recentUser',arrayContainsAny: ['userId'])
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CupertinoActivityIndicator()
);
}
final data = snapshot.data!.docs;
in the Firestore collection I have a document which have userId Field and an array of user ID.
I am trying to retrieve the list of user and for a specific user I want to retrieve just the user that the id is in the array recentUser
As per above example I have tried to user .where('recentUser',arrayContainsAny: ['userId'])
but unsuccesfully...
Any idea?
try replacing ['userId'] with [userId] or ['$userId'] depending on type

How can i fetch data from Firestore (the cashed data) in flutter

i am trying to save data reads which have been not changed yet to avoid more and more the same repeated data that not changed yet ..
i have normal Future.Builder that get data from firstore (network side)
Widget build(BuildContext context) {
return FutureBuilder(
future: FirebaseFirestore.instance.collection('users').get(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Expanded(child: SizedBox()) ;
}
return ListView.builder(
itemCount: snapshot.data!.docs.length ,
itemBuilder: (context, int index) {
DocumentSnapshot documentSnapshot = snapshot.data!.docs[index];
return ListView.builder(
itemCount: snapshot.data!.docs.length ,
itemBuilder: (context, int index) {
DocumentSnapshot documentSnapshot = snapshot.data!.docs[index];
return Text(documentSnapshot['products'])
}
);
}
}
and i have into every single document Timestamp and i need to use where('modify',isGreaterThen : HERE i need to put the old timestamp from cashe to chick if it not changed yet to decide to fetch the new ones
in flutter i cannot handle it as well .. How can i fetch the cashed data with the new ones from network in the harmonic index such as reading the whole data in normal way .. so i avoided these old ones to be reload again ..
i have read a lot of this topic but it was in old Firestore version also it was using java code ...
this following code that cannot handle in flutter
Source CACHE = Source.CACHE;
Source SERVER = Source.SERVER;
Query.Direction DESCENDING = Query.Direction.DESCENDING;
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference shoesRef = rootRef.collection("shoes");
Query lastAddedQuery = shoesRef.orderBy("lastModified", DESCENDING)
shoesRef.get(CACHE).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
boolean isEmpty = task.getResult().isEmpty();
if (isEmpty) {
shoesRef.get(SERVER).addOnCompleteListener(/* ... */);
}
}
});
Query query = shoesRef.orderBy("lastModified", DESCENDING)
.whereGreaterThan("lastModified", savedDate);
source code was written by Alex Mamo
https://medium.com/firebase-tips-tricks/how-to-drastically-reduce-the-number-of-reads-when-no-documents-are-changed-in-firestore-8760e2f25e9e
any support or example with latest version of Firbase and in dart or flutter code will be so thankful ..
best regards

Why am I getting this error Bad state: field does not exist within the DocumentSnapshotPlatform while using firestore?

Bad state: field does not exist within the DocumentSnapshotPlatform
The relevant error-causing widget was
StreamBuilder<QuerySnapshot<Object?>>
StreamBuilder:file:///D:/EgoPro/Flutter%20Apps/task_app/lib/screens/task_screen.dart:189:13
this is the error
StreamBuilder<QuerySnapshot>(
// <2> Pass `Stream<QuerySnapshot>` to stream
stream:
FirebaseFirestore.instance.collection('tasks').snapshots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
final List<DocumentSnapshot> documents = snapshot.data!.docs;
print(documents);
return ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: documents
.map(
(doc) => Meetingcard(
id: doc.get("id"),
title: doc.get("title"),
description: doc.get("description"),
time: TimeOfDay.now()),
)
.toList());
} else if (snapshot.hasError) {
return Text("'It's Error!'");
} else {
return CircularProgressIndicator();
}
},
)
Why am i getting this error ?
This is the image of my documents
enter image description here>
doc.get will return this error if the specified field does not exists in the document. So one of your fields: id, title, description (or more of these) can't be found in doc.
You can add a breakpoint or log and check the result of doc.data() inside your .map((doc)... to see what does it contain.
(One of the possible ways to handle optional fields is to define a model class, create converter where you handle missing values and assign empty string or other default value, so when you read data from your stream you can use this model, and you don't have to handle missing values there.)
EDIT:
Based on the error picture in comment the error seems to be somewhere else, where you assign value to documents. snapshot.data!.docs has the type List<QueryDocumentSnapshot<Object?>> and not `List. Try the following code:
StreamBuilder<QuerySnapshot>(
// <2> Pass `Stream<QuerySnapshot>` to stream
stream:
FirebaseFirestore.instance.collection('tasks').snapshots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
return ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: snapshot.data!.docs
.map(
(DocumentSnapshot doc) => Meetingcard(
id: doc.data()!["id"],
title: doc.data()!["title"],
description: data()!["description"],
time: TimeOfDay.now()),
)
.toList());
} else if (snapshot.hasError) {
return Text("'It's Error!'");
} else {
return CircularProgressIndicator();
}
},
)

Itembuilder doesn't execute in streambuilder, when updating data in firestore

When I launch the app for the first time it loads in all the items into the animated list. But when If I add an item to firestore, the streambuilder realizes something has happend. BUT it doesn't execute the itembuilder so no new items will show up. However if I relaunches the app, the new items will be loaded. If I would just change a name on an existing item on the firestore database, it will rebuild with no problem.
When I update an item. I have to get the map of tasks and replace it with a new copy that has the item and post/update that to firestore.
I have tried everything I can think off, doesn't get why this happens.
I have printed in the itembuilder and can see that it doesn't execute on an update.
Widget _buildTasksList() {
return new Expanded(
child: new StreamBuilder(
stream: Firestore.instance
.collection("lists")
.document(tasklist.postID)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
var listdata = snapshot.data;
tasklist.tasks = listdata['tasks'];
tasklist.owners = listdata['owners'];
tasklist.sorter = listdata['sorter'];
return new AnimatedList(
initialItemCount: convertToTaskList(listdata['tasks']).length,
key: _listKey,
itemBuilder: (context, index, animation) {
return new TaskRow(
task: this.listModel[index],
animation: animation,
listModel: this.listModel,
tasklist: tasklist,
onChange: () => _onChange(this.listModel[index]),
);
},
);
},
)
);
}
Got it working by resetting my _listKey, added this before animated list.
_listKey = null;
_listKey = new GlobalKey();