Flutter & Firestore: How do I get the most recent first? - firebase

How do I get the most recent first from Firestore?
FirebaseFirestore.instance.collection(Strings.factsText)
.where(
Strings.category,
whereIn: [Strings.climateChange])
.orderBy('timestamp', descending: true)
.snapshots(),
...
final factsDocs = snapshot.data.documents;
return FactsListContainer(factsDocs: factsDocs);
});
The issue appears to be with .where when using with .orderBy!

If you have a createdAt field with a timestamp, or an otherwise always incrementing value, you can get the snapshots in descending order of that field with:
stream: FirebaseFirestore.instance
.collection(Strings.factsText)
.orderBy('timestamp', descending: true)
.where(
Strings.category,
whereIn: [Strings.climateChange])
.snapshots(),
Also see the FlutterFire documentation on the Query.orderBy method.

I finally solved it by creating an index in the Firebase console and this worked perfectly so now I'm getting the latest first.
In my database I went to Indexes to create a new index, added my collection name, and then for the fields I added 'category' - descending and 'timestamp' - descending, clicked Collection and then Create Index.

Related

Compare DocumentReference(s) in Firestore with .where()

How to compare DocumentReference references? In this example (with Dart) I only want to fetch tickets from a specific user.
late Query<Map<String, dynamic>> _query;
late DocumentReference<Map<String, dynamic>> _userDocumentReference;
_userDocumentReference = _firestore.collection('users').doc(userId);
_query = _firestore
.collection('tickets'),
//Does not work here
.where('user_id', isEqualTo: _userDocumentReference)
.orderBy('created_at', descending: isDesc)
.limit(7);
I've found the solution by creating an index in FireStore. Check your Debug Console because there it provides a link to create the index to your collection automatically.
It looks like this:
https://console.firebase.google.com/v1/r/project/{project}/firestore/indexes?create_composite=...,

firestore using "where" and "orderBy"

I am trying to run a simple query on Firestore, using both where and orderBy. The query does not work. After some research, I found out that I might need to build index in Firestore. I did that, but once again, this query does not work.
error result
The initial orderBy() field "[[FieldPath([lastTime]), true]][0][0]" has to be the same as the where() field parameter "FieldPath([lastChat])" when an inequality operator is invoked. 'package:cloud_firestore/src/query.dart': package:cloud_firestore/src/query.dart:1 Failed assertion: line 456 pos 13: 'field == orders[0][0]
here is the code:
Stream<QuerySnapshot<Map<String, dynamic>>> chatsStream(String email) {
var result = firestore
.collection('users')
.doc(email)
.collection("chats")
.where("lastChat", isNotEqualTo: "")
.orderBy("lastTime", descending: true)
.snapshots();
return result;
}
and this is index in firestore:
sorry for my english, thanks.
You need to specify an orderBy for the lastChat field, as isNotEqualTo is a range condition (it helps to think of it as <> for that purpose):
var result = firestore
.collection('users')
.doc(email)
.collection("chats")
.orderBy("lastChat")
.where("lastChat", isNotEqualTo: "")
.orderBy("lastTime", descending: true)
.snapshots();
The index on lastTime is ascending, but your query is descending. That means the index doesn't match the query, and the database will return no results.
It should actually also log a warning/error with a direct link to create the index with all fields pre-populated (including the correct sort order for lastTime).

Flutter Firestore Query with arrayContainsAny : List is not working

With latest version of: Flutter + cloud_firestore: ^0.14.0+2
Code:
FutureBuilder(
future: _sessionsLogCollection
.where('companyId', isEqualTo: sPData.companyId)
.where('locationId', arrayContainsAny: [
'29L73oSzdQrzLUow3Mg9',
'bugdWVC6RRtHoemuxNWE',
])
// .where('locationId', isEqualTo: 'bugdWVC6RRtHoemuxNWE')
.orderBy('openDateTime', descending: true)
.get(),
I already have indexes created, so that isn't the problem.
When using .where('locationId', isEqualTo: 'bugdWVC6RRtHoemuxNWE') alone, the query returns the correct data.
But with .where('locationId', arrayContainsAny: ['29L73oSzdQrzLUow3Mg9','bugdWVC6RRtHoemuxNWE']) alone, it does not give any error, but simply returns empty data set: sessionsSnapShot.data.documents.length: 0.
** Solved with .whereIn (Probably .whereIn should be included at firebase.flutter.dev/docs/firestore/usage as it is not currently there)
According to your code .where('locationId', isEqualTo: 'bugdWVC6RRtHoemuxNWE'), it seems that locationId is not an array, instead it is a field. If you want to query an array you can only use arrayContains and arrayContainsAny. But since this is a field then you have to use whereIn:
.where('locationId', whereIn: [
'29L73oSzdQrzLUow3Mg9',
'bugdWVC6RRtHoemuxNWE',
])
Use the in operator to combine up to 10 equality (==) clauses on the same field with a logical OR. An in query returns documents where the given field matches any of the comparison values
https://firebase.google.com/docs/firestore/query-data/queries#array_membership
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/cloud_firestore/cloud_firestore/lib/src/query.dart#L393

How to check if an array in a firestore document is empty?

I'm building out an app in flutter and I want to run a query to determine if the array in my firestore document is empty. Is there a way to do this?
Here is a picture of my data structured in firestore.
I know there is an arrayContains method but I'm not sure on how to check for an empty array. Here is my current code.
_postsStream = await _firestore
.collectionGroup('posts')
.where('timestamp', isGreaterThanOrEqualTo: _start)
.where('timestamp', isLessThanOrEqualTo: _end)
.where('problems', arrayContains: )
.snapshots();
I left the arrayContains: intentionally empty for now. Please advise on how I would go about implementing this feature. Thanks in advance!
An empty array defaults to [] So this is possible by doing the following:
Do not use ' ' for the square brackets
final _database = Firestore.instance;
return _database
.collection('arrays')
.document(arrId)
.where('array', isEqualTo: [])
// .where('array', isNull: true) can be used to check if it's null
.snapshots()
.map(_itemListFromSnapshot);
You cannot do it in firestore currently.
What you can do is.
Create a separate property hasProblems which defaults to false.
If the user try to register a problem, then check the flag hasProblems.
If hasProblems==false, then toggle it to true and add the problem to the list.
else no need to toggle, just add the new problem to the list.
If problems are to be removed later on, then check for the list to get empty.
Once it is empty, then toggle hasProblems back to false.
This way you can achieve what you want-
postsStream = await _firestore
.collectionGroup('posts')
.where('timestamp', isGreaterThanOrEqualTo: _start)
.where('timestamp', isLessThanOrEqualTo: _end)
.where('hasProblems',isEqualsTo: false)
.snapshots();
Maybe you can have other better solutions, but this is the one that came in my mind.
You can follow the solution #mubin986 has given, but once the list gets bigger and bigger, it impacts performance.
Cheers, hope it helps.
There is no way to check with firestore query if an array is empty or not.
But, you can follow these steps:
Query the data with range filters:
_postsStream = await _firestore.collectionGroup('posts')
.where('timestamp', isGreaterThanOrEqualTo: _start)
.where('timestamp', isLessThanOrEqualTo: _end)
.snapshots();
After fetching the data, iterate over all the DocumentSnapshot and check if problems array is empty or not.

How to fetch records by comparing with date in flutter cloud firestore plugin?

Working on a flutter application where I'm using firebase cloud firestore for storing all my documents. My document has a startDateTime field having a format like this...
I want to fetch all records whose startDateTime is greater than or equal to current date. Here is my flutter code to do this...
Firestore.instance.collection("trips")
.where("trip.createdByUID", isEqualTo: this.userDetails['id'])
.where("trip.startDateTime", isGreaterThanOrEqualTo: new DateTime.now().toString() )
.getDocuments().then((string) {
print('Firestore response111: , ${string.documents.length}');
string.documents.forEach((doc) => print("Firestore response222: ${doc.data.toString()}" ));
})
But this is not working. Can't able to understand how to use isGreaterThanOrEqualTo so that it'll work.
Need some guidance.
Pass just this query
.where("trip.startDateTime", isGreaterThanOrEqualTo: new DateTime.now())
Since firebase automatically converts dart DateTime object to Timestamp Firebase object. You also need to do the same when you save the object.
You can see on the right if the object type is timestamp.
In case this doesn't work, you can save another object on your creation in numeric format. Then it is easy to compare. You can get numeric dateTime like this:
new DateTime.now().millisecondsSinceEpoch
You can compare by anything like day or by hour using DateTime():
final response = await FirebaseFirestore.instance
.collection('meetings')
.where(
'date',
isGreaterThanOrEqualTo: DateTime(selectedDay.year, selectedDay.month, selectedDay.day)
)
.get();
I got it working on iOS. Please check the code below.
DateTime _now = DateTime.now();
return StreamBuilder<QuerySnapshot>(
stream: _store
.collection('rides')
.orderBy('rideDate')
.orderBy('rideType')
.where('rideDate', isGreaterThan: _now)
.snapshots(),

Resources