Firestore end before documents not working properly - firebase

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();

Related

Merge two streams coming from firebase firestore Flutter

I want two streams to be combined as one result and then return it from my function. I have two streams coming from firebase. So I have to merge data1 into data2, something like concatenation of both the streams and then return. What i have acheived so for is:
Future<Stream<QuerySnapshot>> getMsgs(userId, toId) async {
var data1 = await _fireStore
.collection(_collection)
.where('messageFrom', isEqualTo: userId).where('messageTo', isEqualTo: toId)
.orderBy('createdOn', descending: true)
.snapshots();
var data2 = await _fireStore
.collection(_collection)
.where('messageFrom', isEqualTo: toId).where('messageTo', isEqualTo: userId)
.orderBy('createdOn', descending: true)
.snapshots();
// I have tried this, but this will be the list
return [data1, data2];
// I have tried this, but didn't worked
return StreamZip([data1, data2]);
}
Any help would be appreciated.

flutter firebase order by in a condition

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.

How can I pack a snapshot into a string?

Can I pack a snapshot data from firebase into a string to use it anywhere else?
Firestore.instance
.collection('users')
.document(uid)
.collection('usergroups')
.snapshots(),
You can not use snapshots because it will return stream if you want to to use somewhere else then you have to use getDocuments which will return future.
Note: as you get update of data in snapshot, you will not get in getDocuments.
How to use it.
QuerySnapshot i =
await Firestore.instance.collection("data").getDocuments();
print(i.documents);
You can do like this
Stream<QuerySnapshot> snapshots = Firestore.instance.collection('users').document(uid).collection('usergroups').snapshots()

Firestore Query by timestemp with flutter

I am adding a document to my collection like this.
void addToDb() {
collectionReference.add({
'dateTime': FieldValue.serverTimestamp(),
});}
i am trying to query data after a certain date time like this
Firestore.instance
.collection('items')
.orderBy('dateTime', descending: true).startAt([{'dateTime' : DateTime.parse('2019-03-13 16:49:42.044')}])
.snapshots(),
When i set descending to true, i get back all the docs.
When i set to false i get back none.
Both are not expected results.
I seen a few on stack saying to convert date time to just milliseconds or unix. but i am using the servertimestamp because i cant trust the client to write the time stamp. Any idea how i can query date time ranges with servertimestamp?
I can't really explain why this works, but this works for me.
final startAtTimestamp = Timestamp.fromMillisecondsSinceEpoch(DateTime.parse('2019-03-13 16:49:42.044').millisecondsSinceEpoch);
Firestore.instance
.collection('items')
.orderBy('dateTime', descending: true).startAt([startAtTimestamp])
.snapshots()
Also you can do as follows,
Firestore.instance
.collection("driverListedRides")
.where("uid", isEqualTo: widget.uid.toString())
.where("status", isEqualTo: "active")
.where("date",
isGreaterThanOrEqualTo:
DateTime.now().toString().split(" ")[0].toString())
.orderBy("date", descending: true)
.orderBy("time", descending: false)

FireStore Error in Cursor - cursor position is outside the range

I have a method to return some data from FireStore, which is used for pagination in my Flutter app.
static Future<QuerySnapshot> getAllItems({int count: 12, dynamic lastKey}) {
if (lastKey != null) {
return Firestore.instance
.collection('uploads')
.where('active', isEqualTo: true)
.where('purge', isEqualTo: false)
.startAfter([lastKey])
.orderBy("active_time", descending: true)
.where('active_time', isLessThanOrEqualTo: DateTime.now())
.limit(count)
.getDocuments();
} else {
return Firestore.instance
.collection('uploads')
.where('active', isEqualTo: true)
.where('purge', isEqualTo: false)
.orderBy("active_time", descending: true)
.where('active_time', isLessThanOrEqualTo: DateTime.now())
.limit(count)
.getDocuments();
}
}
When lastKey value is not passed, all works fine. But when I pass the string value of lastKey, I get the below error.
cursor position is outside the range of the original query
The field active_time is a TimeStamp type in FireStore. Index is created for the same.
Since active_time is a DateTime, lastKey should also be a DateTime.
From the Docs on startAfter
Takes a list of values, creates and returns a new Query that starts
after the provided fields relative to the order of the query.
https://pub.dartlang.org/documentation/cloud_firestore/latest/cloud_firestore/Query/startAfter.html
Let me document the issue I faced.
The issue was due to the difference of data type. The Firebase database and my dart variable type was different.. ie.. DateTime and Timestamp. After fixing this, the code started to work.

Resources