the probleme in my code is whenever i add the orderby my code stops working and the data is not displaying even when i don't get any errors
here's the stream i sued :
Stream<QuerySnapshot> searchData(String textEntered) async* {
var _search = FirebaseFirestore.instance
.collection("users")
.doc(sharedPreferences!.getString("uid"))
.collection("inventaire")
.doc(widget.model!.InventoryID)
.collection("produits").where('BarCode', isGreaterThanOrEqualTo: textEntered).orderBy('LastUpdate', descending: true)
.snapshots();
yield* _search;
}
I'm guessing now, as there isn't much to go on. But you are probably missing an index for the query.
Check your logs if you get anything like: " The query requires an index."
You can read more about it at:
https://firebase.google.com/docs/firestore/query-data/indexing
Another alternative is using a StreamController to return a modified stream, that way you could refactor the code into a listen:
Stream<QuerySnapshot> searchData(String textEntered) {
var controller = StreamController<QuerySnapshot>();
FirebaseFirestore.instance
.collection("users")
.doc(sharedPreferences!.getString("uid"))
.collection("inventaire")
.doc(widget.model!.InventoryID)
.collection("produits").where('BarCode', isGreaterThanOrEqualTo: textEntered).orderBy('LastUpdate', descending: true)
.snapshots().listen((QuerySnapshot qSnapshot) {
controller.add(qSnapshot);
});
return controller.stream;
}
Using the StreamController could even allow you to map the documents out of the QuerySnapshot returned on the listen callback handler and instead returning a list of PODO objects already mapped as opposed to the QuerySnapshot. My two cents.
This is how I am getting the data from the Firebase but I want to implement a Filter system in my app by which the request changes like if I take a data from the user like where price is lower than this and I add it in a string and pass that string into this query and it gives me data according to it.
response = await FirebaseFirestore.instance
.collection("posts")
.where('type', isEqualTo: widget.type)
.where('sellercity', isEqualTo: widget.city)
.limit(documentLimit)
.get();
For example I add a string name State = ".where('sellercity', isEqualTo: "userdata")" to the query where userdata will be null;
like this
.collection("posts")
.where('type', isEqualTo: widget.type)
+ State +
.where('sellercity', isEqualTo: widget.city)
and it works normally but when the user add something to the userdata and it changes and refreshes the data according to it.
Please tell me how can I do this and is there any tutorial or something for it.
Make the initial value of userdata to null
String userdata = null;
then pass it in the query like this and it'll not effect the search
.where('sellercity', isEqualTo: widget.city)
Then you can update the userdata by taking input from the user and can update the query.
I am using the below query to get documents before given documents snapshot. when I use descending: false
I get initial 5 documents but I want immediate 5 documents before the given documents. When I use descending: true I get an empty list. Please help me. What I am doing wrong here.
Stream<QuerySnapshot> getConversationBefore(String currentUserID,String clientID,DocumentSnapshot documentSnapshot)
{
return Firestore.instance
.collection(FIREBASE_COLLECTION_MESSAGES)
.document(currentUserID)
.collection(clientID)
.orderBy(TIMESTAMP_FIELD, descending: false)
.endBeforeDocument(documentSnapshot)
.limit(5)
.snapshots();
}
EDIT:
Also make sure you have initialized an index on the field you are trying to order by, take a look here!
return Firestore.instance
.collection(FIREBASE_COLLECTION_MESSAGES)
.document(currentUserID)
.collection(clientID)
.orderBy('TIMESTAMP_FIELD', descending: true)
.endBeforeDocument(documentSnapshot)
.limit(5)
.snapshots();
In Dart/Flutter and learning Firebase Firestore... I'm using the following method to test before creating UI:
_testFireStore() async {
var result = Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1')
.snapshots();
await for (var snapshot in result) {
for (var user in snapshot.documents) {
print('main.DEBUG: ' + user.data.toString());
}
}
}
It works as expected -- the print statement is executed initially, but also subsequently in real-time every time any field is updated in the document in the Firestore database.
How can this code be changed such that the snapshot is only retrieved once -- not "subscribed/listened" to... and thus we don't waste bandwidth on unwanted/unneeded data and the print statement is only executed once?
Firestore.instance.collection(...).where(...) returns a Query object. It has a method called getDocuments() that executes the query and gives you a Future with a single set of results.
var query = Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1');
query.getDocuments().then((QuerySnapshot snapshot) {
// handle the results here
})
Or use await to get the QuerySnapshot, since getDocumets() returns a Future.
Use getDocuments(), to retrieve all the documents once:
_testFireStore() async {
var result = await Firestore.instance
.collection('users')
.where('uid', isEqualTo: 'IvBEiD990Vh0D9t24l2GCCdsrAf1')
.getDocuments();
print(result.documents.toString());
}
I am building a flutter app and using Cloud Firestore. I want to get the number of documents in the database.
I tried
Firestore.instance.collection('products').toString().length
but it didn't work.
Firebase doesn't officially give any function to retrieve the number of documents in a collection, instead you can get all the documents of the collection and get the length of it..
There are two ways:
1)
final int documents = await Firestore.instance.collection('products').snapshots().length;
This returns a value of int. But, if you don't use await, it returns a Future.
2)
final QuerySnapshot qSnap = await Firestore.instance.collection('products').getDocuments();
final int documents = qSnap.documents.length;
This returns a value of int.
However, these both methods gets all the documents in the collection and counts it.
Thank you
With Cloud Firebase 2.0, there is a new way to count documents in a collection. According to reference notes, the count does not count as a read per document but a metaData request:
"[AggregateQuery] represents the data at a particular location for retrieving metadata without retrieving the actual documents."
Example:
final CollectionReference<Map<String, dynamic>> productList = FirebaseFirestore.instance.collection('products');
Future<int> countProducts() async {
AggregateQuerySnapshot query = await productList.count().get();
debugPrint('The number of products: ${query.count}');
return query.count;
}
It Should Be - Firestore.instance.collection('products').snapshots().length.toString();
Since you are waiting on a future, this must be place within an async function
QuerySnapshot productCollection = await
Firestore.instance.collection('products').get();
int productCount = productCollection.size();
Amount of documents in the collection
Future<int> getCount() async {
int count = await FirebaseFirestore.instance
.collection('collection')
.get()
.then((value) => value.size);
return count;
}
Instead of getting all the documents using get() or snapshots() and counting them, we can use Firebase Aggregation Queries. This will provide you with the count.
Here is an example that works in Flutter :
final collection = FirebaseFirestore.instance.collection("products");
final query = collection.where("status", isEqualTo: "active");
final countQuery = query.count();
final AggregateQuerySnapshot snapshot = await countQuery.get();
debugPrint("Count: ${snapshot.count}");
You can find more details here : https://firebase.google.com/docs/firestore/query-data/aggregation-queries
First, you have to get all the documents from that collection, then you can get the length of all the documents by document List. The below could should get the job done.
Firestore.instance.collection('products').getDocuments.then((myDocuments){
print("${myDocuments.documents.length}");
});
Future getCount({String id}) async => FirebaseFirestore.instance
.collection(collection) //your collectionref
.where('deleted', isEqualTo: false)
.get()
.then((value) {
var count = 0;
count = value.docs.length;
return count;
});
this is in dart language...
Above suggestions will cause the client to download all of the documents in the collection to get the count. As a workaround, if your write operations are not frequently happening, you can put the length of the documents to firebase remote config and change it whenever you add/delete documents from the Firestore collection. Then you can fetch the length from firebase remote configs when you need it.
Most Simplest Way :
int count = await FirebaseFirestore.instance.collection('Collection_Name').get().then((value) => value.size);
print(count);
You want to fetch data from firebase so the call will return a Future.
In order to get the int value you have to use the StreamBuilder widget or FutureBuilder.
For example:
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("<collection name>").getStream().snapshot(),
builder: (context, snapshot) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Stack(children: [
Text(
"${snapshot.data!.docs.length}"
)
]));
});
}
Firestore.instance
.collection("products")
.get()
.then((QuerySnapshot querySnapshot) {
print(querySnapshot.docs.length);
});
#2022 Using the recent version of FirebaseFirestore you can now get the count without retrieving the entire collection.
CollectionReference ref = FirebaseFirestore.instance.collection('collection');
int count = (await ref.count().get()).count;