Pagination across multiple sub-collections

648 views
Skip to first unread message

Karthick Subramanian

unread,
Nov 1, 2019, 5:25:57 PM11/1/19
to fireba...@googlegroups.com
Hi,

I am struggling to work out this. I have a collection called "University". It has "College" as sub-collection. Each College sub-collection contains Departments Subcollection. Each department sub-collection contains students, professors etc as individual user documents as they register to the courses. 

As a University admin, he wants to see the list of students registered for this academic year. I need to do pagination. Since I am traversing  "students" records across various sub-collection, getting the records and apply pagination is challenging. Because sometimes pagination item size overflow to next sub-collection. 

Is there an efficient way, I can achieve in this scenario. Thank you. 


Tyler Rockwood

unread,
Nov 3, 2019, 4:32:55 PM11/3/19
to Firebase Google Group
Hello Kart!

Thanks for explaining your schema. I believe you can make this work with Collection Group Queries [1]. The only caveat is that you also need to store the university as part of the Student document.

Query:
db.collectionGroup('Students').where('university', '==', <university>).onSnapshot(...);
Rules:
match /**/Students/ { allow list: if userIsAdminForUniversity(resource.data.university) }

There is a more complex solution if you don't want to add that field to all Student records, but the rules would be more complex (I'd need to experiment here).

db.collectionGroup('Students')
.where(FieldPath.documentId(), '>', '/University/<university>')
.where(FieldPath.documentId(), '<', '/University/<university>\0'); // note that is the null byte at the end


Note all those code snippets have not been tested so tweaks might be needed :)

Pagination is described in our docs [2].

Let me know if that would work for your use case, or if you have other questions.

-Tyler


[1]: https://firebase.googleblog.com/2019/06/understanding-collection-group-queries.html

[2]: https://firebase.google.com/docs/firestore/query-data/query-cursors

Karthick Subramanian

unread,
Nov 4, 2019, 9:14:15 AM11/4/19
to fireba...@googlegroups.com
Thank you very much Tyler for sharing this details. I will go thru this and experiment it and update group if further assistance required. 

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/032f1784-4701-4374-afec-1cdeb7ed2bb9%40googlegroups.com.

Tracy Hall

unread,
Jan 17, 2020, 7:03:11 PM1/17/20
to Firebase Google Group
Tyler:

In your example you use:
db.collectionGroup('Students')
  .where(FieldPath.documentId(), '>', '/University/<university>')

...but '/University/<university>' is a partial refPath, not a documentId.  Yes, the hack *works* but it seems to rely on what *must* be a bug.

There *should* be *two separate functions:

FieldPath.refPath() // which returns the full refPath to compare/query against

**AND**

FieldPath.documentId() //which returns the document Id to compare/query against

As it is, I've seen a few "answers" use FieldPath.documentId() to match/compare against refPath's, but it seems to be a mistake!

m...@google.com

unread,
Jan 27, 2020, 6:00:18 PM1/27/20
to Firebase Google Group
FieldPath.documentId() actually matches the full path so this works as expected and this is intended.

FieldPath.documentId() is unfortunately named. It was created before collection group queries existed, and was named that way because we expected this to be the common form of a query:

    db.collection('/University')
        .where(FieldPath.documentId(), '==', '<university>')

Under the covers the SDK prepends the collection path to any id-only queries to make it a full path. This is because the only way Firestore can match a document is on its full path. There's no way to match on just the id.

The issue with collection group queries is that there's no collection path to prepend, and this forces you to specify the full path in the argument. That in turn makes the naming of FieldPath.documentId() seem awkward.

Cheers,
-Gil

Adam Weisberg

unread,
Jan 28, 2020, 8:16:19 PM1/28/20
to fireba...@googlegroups.com
hi Tracy - in Firestore I think the documentId is by definition the same as the document part of the ref, as in {collectionName}/{documentId}. Because unlike any relational database, the document's unique ID isn't a field/column of the record. It's really just the same name that identifies it within the document collection. 

So yeah it'd be crazy in a regular database, but in this framework specifying a docID as part of a refPath actually does make sense. 

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages