I'm trying to query a set of 5 records from my firestore database. Every time the client successfully queries 5 records, each record's view field on the document increments by 1. I basically want all records in the database to get an equal chance to be seen on the client side so records with the lowest view value should get queried. However, the following query doesn't behave as expected as I keep getting the same set of records even though the queried records now have higher view values. Doesn't orderBy with descending set to false sort the collection to have the lowest value listed first?
QuerySnapshot snapshot = await FirebaseFirestore.instance
.collection('records')
.where('city', isEqualTo: city)
.where('views', isGreaterThan: -1)
.orderBy('views', descending: false)
.limit(5)
.get();
snapshot.docs.forEach((element) async {
Record record =
Record.fromMap(element.data() as Map<String, dynamic>);
await FirebaseFirestore.instance
.collection('records')
.doc(record.recordID)
.update({'views': FieldValue.increment(1)});
}
}
Doc id and view logs after first query:
- I/flutter ( 3630): e56a4c40-40e5-11ec-9a4b-b5164e53b334
- I/flutter ( 3630): 4
- I/flutter ( 3630): ecd328c0-40e6-11ec-a76a-cd0a98374153
- I/flutter ( 3630): 4
- I/flutter ( 3630): dc894420-40e3-11ec-a113-2d0055afb86b
- I/flutter ( 3630): 4
- I/flutter ( 3630): e3f554f0-40e4-11ec-a3ae-1f948418cef9
- I/flutter ( 3630): 4
Doc log and views 2nd query:
- I/flutter ( 3630): ecd328c0-40e6-11ec-a76a-cd0a98374153
- I/flutter ( 3630): 5
- I/flutter ( 3630): e56a4c40-40e5-11ec-9a4b-b5164e53b334
- I/flutter ( 3630): 5
- I/flutter ( 3630): dc894420-40e3-11ec-a113-2d0055afb86b
- I/flutter ( 3630): 5
- I/flutter ( 3630): e3f554f0-40e4-11ec-a3ae-1f948418cef9
- I/flutter ( 3630): 5
CodePudding user response:
Take a look at the orderBy
prop in getBy
function in https://www.npmjs.com/package/firebase-firestore-helper
You should be able to do something like:
db.getBy({ where: [{ city }, ['views' '>', -1]], orderBy: ['views', 'desc'] });
Then, in your code, get the first 5.
I'm not 100% sure about this, but the limit
gets executed BEFORE the orderBy
.
And that is a problem, because, again, as far as I remember (I may be wrong), Firebase will work as this:
- First, get ALL view > -1
- Then, get only the 5 first elements
- Finally, order the resulting 5 elements and retrieve them.
Again: I'm not 100% sure about this, but I remember having the same problem as you.
If somebody say I'm wrong, I'll remove this answer.
Check something here https://firebase.google.com/docs/firestore/query-data/order-limit-data
Disclaimer: I am the creator of this library. It helps to manipulate objects in Firebase Firestore (and adds Cache)
Enjoy!
CodePudding user response:
I'm not sure what explains the behavior, but if you remove the descending parameter after orderBy
, it works. I'm not sure why the descending parameter was causing an issue.
orderBy('views')
defaults to false
for the descending parameter if nothing is provided anyway.