12

Sorry I have seen this question has been asked many times in different ways here such as:

But NONE of the answers really explain the solution or are understandable.

Also I went though many tutorials such as:

To details:

So here is what I have done so far

let query = ref.orderBy(orderBy, asc ? 'asc' : 'desc').limit(limit);
        if (startAfter) {
          // Thiis works as it should
          query = query.startAfter(startAfter);
        }
        if (endBefore) {
          // This here does not work or give the correct results. I get the first page. 
          query = query.endBefore(endBefore);
        }
        return query;

So:

query = query.startAfter(startAfter); works as expected.

However:

query = query.endBefore(endBefore) does not end before that document I think it ends up to the limit.

Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117

2 Answers2

25

As of firebase@7.3.0 you can use the Query.limitToLast(n: number) method - makes it much easier to move backward with paginated data.

Your implementation details might look something like this:

function nextPage(last) {
   return ref.orderBy('age').startAfter(last.age).limit(3);
}

function prevPage(first) {
   return ref.orderBy('age').endBefore(first.age).limitToLast(3);
}
JeffD23
  • 8,318
  • 2
  • 32
  • 41
  • Do you think this should be the correct answer? I am asking because I have not tried this as of I dont know if there are any differences and most important limitations with this. – Jimmy Kane Nov 13 '19 at 11:29
  • 2
    No need to change, I just wanted to make sure the option shows up here since it's a brand new feature in the SDK. Will only work for apps on 7.3 or later. – JeffD23 Nov 13 '19 at 14:16
  • I ll wait some time , let the users upbring yours and then ill change this so we can cover I think a good portion of help – Jimmy Kane Jan 19 '20 at 20:34
  • limitToLast() did the trick for me (for navigating to previous page). – Faraz Ahmad Apr 18 '20 at 22:09
  • I made this the correct answer since you got the peoples choice :-D Thanks for this :-D – Jimmy Kane Oct 10 '20 at 17:39
  • why does limitToLast brings last two results as well? productRef.endBefore(getSnapOfLast).limitToLast(recordSize).get() – bitsedegitsek Jan 22 '21 at 14:11
10

So I think I solved it by a comment inspired by the github issue mentioned above:

Supposing you have this array and you are sorting ascending

A,
B, 
C,
D,
E,
F, 

And you have a page limnit of 2 results

Then when you are in the third page you should have

E,
F

Now you need to go to previous page and what you need todo is:

  1. Reverse the sorting order and our data should be [F,E,D,C,B,A]
  2. startAfter the first document of the currently viewed page (in our case E)
  3. Query the firestore to get the results (eg with your limit of 2). You should get with reverse order and starting after E and that is [D,C]
  4. Reverse the above array so it will be [C,D]
  5. Done
Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125
Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117
  • 1
    @f.khantsis hey! Doom777? From AGM maps? Dimitrios kanellopoulos here we have talked. It sucks big time and worse is that the firebase team does not help with these queries. – Jimmy Kane Jul 25 '19 at 14:21
  • 2
    thank you for the idea. i was struggling to achieve this. – neuraminidase7 Jul 26 '19 at 09:12
  • 1
    Hey @JimmyKane, nice answer! They don't even want to address this as "an issue": https://github.com/firebase/firebase-js-sdk/issues/479 While I understand that their NoSQL database structure can't exactly handle this approach, they should at least give an opinion on how to solve this in a decent manner, but they prefer to simply accept the fact that "Firestore is not your DB", which sucks, because in Firebase, there is not SQL alternative (or other NoSQL that can handle this approach). – Guilherme Matuella Aug 27 '19 at 21:42
  • 1
    thanks Jimmy I applied your logic to my vuexfire app as well. only caveat is how step 4 reversing the array is done with the document Snapshot object (not array) is done – Akin Hwan Mar 23 '20 at 22:23
  • was trying to implement pagination for a `firestore` application and came across this solution and looked further into it. i would say, while this is a viable solution, you could very easily **go beyond** your usage limits. imagine you have `100` documents in a collection, displaying `10` documents per page and you are now on the last page. executing a previous page means you will be executing `90` reads just to go to the previous page. with `1000` documents, that will be `990` reads. you get my point. so just beware if anyone is going to implement pagination this way. – eugeneoei Apr 22 '20 at 09:57
  • @eugeneoei you put a limit on the page size. This is scalable. Read please again the login. IT says >Query the firestore to get the results (eg with your limit of 2). You should get with reverse order and starting after E and that is [D,C] if you don;t put limits yes, you are right. But then you got the whole logic wrong. – Jimmy Kane Apr 23 '20 at 08:44