Firebase pagination using a timestamp/date as the orderBy

Viewed 728

I am struggling to get pagination working when I use a date (firebase timestamp) to retrieve data.

This is basically what I do:

let jobsRef = db.collection("jobs")
            .orderBy('createdAt', 'desc')
            .limit(QUERY_LIMIT);
jobsRef = jobsRef.startAfter(this.props.jobs[this.props.jobs.length - 1].createdAt);

However it seems that i get returned items sometimes that I have just already received. I am guessing because of similar dates? So how could I basically return a list of jobs ordered by createdAt and have an offset/limit (pagination)?

createdAt looks like the timestamp type: 23 October 2020 at 17:26:31 UTC+2 When I log createdAt however I see this: {seconds: 1603537477, nanoseconds: 411000000} Maybe I should be storing createdAt as a unix timestamp? Or what is the ideal way to deal with this?

Here is how it looks in the database (popup when i click edit on createdAt): enter image description here

2 Answers

If multiple documents can have the same value for the field you're sorting on, passing in a value for that field is not guaranteed to point to a unique document. So you indeed may be passing in an ambiguous instruction, leading to an unwanted result.

When possible, I highly recommend passing the entire document to the Firestore API. This leaves it up to Firestore to take the necessary data from that document to uniquely/unambiguously find the anchor for your query.

So instead of:

jobsRef.startAfter(this.props.jobs[this.props.jobs.length - 1].createdAt);

Do:

jobsRef.startAfter(this.props.jobs[this.props.jobs.length - 1]);

I was facings a similar problem, after may hours I finally found a solution, all you need to do is converting that number to firestore's Timestamp

import { Timestamp }. from @angular/fire/firestore;


let createdAt: number = 56772766688383;

let timestamp = Timestamp.fromMillis(createdAt);

//then pass that to startAfter

startAfter(timestamp)


Related