Home > Mobile >  firstore query skips all documents with same startAfter value
firstore query skips all documents with same startAfter value

Time:08-31

TLDR; firestore skips all the documents that has same startAfter value. How to overcome this limitation.

My firestore postLikers collections keeps a document for each person who liked my post. It stores the UID of the liker, and the epoch timestamp of when the post was liked.

postLikersCol : [
  doc_1 : { uid: uid1, timeOfLike: 1661924000 },
  doc_2 : { uid: uid2, timeOfLike: 1661924001 },
  doc_3 : { uid: uid3, timeOfLike: 1661924002 }, // same time
  doc_4 : { uid: uid4, timeOfLike: 1661924002 }, // same time
  doc_5 : { uid: uid5, timeOfLike: 1661924002 }, // same time
  doc_6 : { uid: uid6, timeOfLike: 1661924003 },
  doc_7 : { uid: uid7, timeOfLike: 1661924004 },
]

and I am readin the data like this :

firestore()
.collection('postLikersCol')
.orderBy('timeOfLike', 'desc')
.startAfter(lastReadDoc.timeOfLike)
.limit(3)
.get()

In the first round of query the .startAfter() is not added so I get last 3 docs (doc_7, doc_6, doc_5, in this order)\

In the second call, .startAfter() is added in query and it takes timeOfLike of the last read document (doc_5) i.e. 1661924002
With this call, the firestore returns doc_2 and doc_1, both of which has timeOfLike < 1661924002

With this scenario, doc_4 and doc_3 are never read !!

Can someone suggest a solution for this, that I can read all documents with .orderBy('timeOfLike', 'desc')


Only solution I thought is using unique orderBy fields. So appending uid with timestamp may work (1661924002_uid3). Is there a better solution ?

CodePudding user response:

OK, so I found that that i can give two orderBy and two startAfter, to overcome this issue.

https://firebase.google.com/docs/firestore/query-data/query-cursors#set_cursor_based_on_multiple_fields

I suppose it will require a compound index (additional cost overhead) But the solution of appending uid to the timestamp also costs more storage, and lengthier data is stored and it's not a number anymore.

Hmm, If you still have a better answer please let me know.

CodePudding user response:

You can use startAfter() with DocumentSnapshot of last document instead of the timestamp value. Try:

const snap = await firestore()
  .collection('postLikersCol')
  .orderBy('timeOfLike', 'desc')
  .startAfter(lastReadDocSnap)
  .limit(3)
  .get()

Here, lastReadDocSnap would be snap.docs[3] i.e. the last document of previous query.

  • Related