3

I've been searching for this one for a while but have not found a reason why this is the way it is.

Basically this returns an array of documents in the collection.

this.db.collection('people', ref => {
    return ref.orderBy(name, 'asc')
              .startAfter(null)
              .limit(10)
})...

This returns an empty array.

this.db.collection('people', ref => {
    return ref.orderBy(name, 'desc')
              .startAfter(null)
              .limit(10)
})...

The only difference is orderBy is set to 'desc'. Can someone please explain why this happens and a way around it? Thanks in advance!

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Kyle Abens
  • 243
  • 4
  • 18

2 Answers2

3

I believe the issue is startAfter(null). When you sort in ascending order, the null docs come first and then the non-null docs. For the exact order, see the Firebase documentation on the ordering of value types.

When you sort in descending order, all the null docs come last so there is nothing after the null docs for the query to return.

I suggest removing startAfter(null) until you have a value for it.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Juan Lara
  • 6,454
  • 1
  • 22
  • 31
  • If I remove startAfter my snapshotChanges fires twice for some reason. Not sure why – Kyle Abens Feb 24 '19 at 03:29
  • Is it firing twice after a write operation? Local writes fire twice, once locally and then again when the write is committed to the database. See the docs on [latency compensation](https://firebase.google.com/docs/firestore/query-data/listen#events-local-changes). – Juan Lara Feb 24 '19 at 09:23
  • Not writes just reads. SnapshotChanges fires twice when I apply a where query to the collection. It looks like it first emits some cached values and then the complete response from the server. – Kyle Abens Feb 24 '19 at 11:50
  • Hope this answer helped. Do you have another question about SnapshotChanges? If so, please post another question with a snippet showing the behavior. – Juan Lara Feb 24 '19 at 22:20
0

if anyone interested with my solution just arrow up:

var lastDocumentSnapshot : DocumentSnapshot? = null;
if (url != null){
    val query = this.getLastDocumentSnapshotAsync(url).await()
     if (!query.isEmpty){
        lastDocumentSnapshot = query.documents.distinct().first()
     }
}

val query = firebaseDb.collection("urls")
    .orderBy("name", sortDirection)
    .limit(limit)
if (sortDirection == Query.Direction.ASCENDING)
    query.startAfter(lastDocumentSnapshot)
else
    query.endBefore(lastDocumentSnapshot)

return query.get().asDeferredAsync()

Don't mind the other parts of the code. basically the fix is to use endBefore if the sort is descending.

Rashid
  • 1,700
  • 1
  • 23
  • 56
  • Hey, I don't understand your code. It does not make good sense to me. But the ```endBefore``` trick worked dor descending order though. Thanks. – Delali Feb 27 '20 at 17:56
  • In my opinion, your code does not directly answer the question asked. For those who are new to the subject, they'll get confused. I got my solution working just by using ```endBefore``` instead of ```startAfter``` like you suggested. That alone should be your answer. – Delali Feb 29 '20 at 07:50