goodson
goodson

Reputation: 757

How to design firestore relations on the server and the client

I'm designing a firestore database, trying to understand no-sql. What's getting me stuck is relationships. I know I'm supposed to keep root level collections and relate them with references, but I don't understand how to manage the relations once the data is on the client. Say this is my data (without relations) ...

Schools (collection)
    JFKElementary (doc)
        address: 123 Elm Street

Classrooms (collection)
    Room1 (doc)
        roomNumber: 1
    Room2 (doc) ...

Families (collection)
    Jones.1234 (doc)
        address: 456 Cherry Lane
    Smith.2134 (doc) ...

Students
    Billy.Jones.2323 (doc)
        name: Billy Jones

I need to represent the idea that "Billy Jones" belongs to the Jones.1234 family, and that he belongs to the Room1 classroom, and that the classroom and the family belong to the JFKElementary school. I know I can place refs in the documents, like this...

Classrooms (collection)
    Room1 (doc)
        roomNumber: 1
        school: ref to JFK Elementary

Students
    Billy.Jones.2323 (doc)
        name: Billy Jones
        family: ref to Jones.1234
        classroom: ref to Room1
        school: ref to JFK Elementary

I want to get a whole school on the client, so I think I can query like this:

collection('classrooms').where("school", "==", <school ref>)  
collection('students').where("school", "==", <school ref>)
// etc for families

That gets me the whole school, but leaves my problem: On the client, how do I assemble the relationships that UI needs? For example, say the UI wants to present the names of all the students in Room1...

let room1 = classroomsSnapshot.docs[0]
let room1Students = studentsSnapshot.docs.filter(student => {
    return student.data().classroom.id === room1.id
})

I wouldn't want all that code run each time I need a room's students. I could build my own class on the client like this?

class ClientSideClassroom {
     constructor(doc, studentsSnapshot) {
        this.doc = doc
        this.students = studentsSnapshot.docs.filter(student => {
            return student.data().classroom.id === room1.id
        })
     }

and on a snapshot...

let clientClassrooms = classroomsSnapshot.docs().map(doc => {
    return new ClientSideClassroom(doc, studentsSnapshot)
})

If so, then the student docs (and all of the others) are going to need their own class, too, e.g. to answer the ClientSideClassroom to which they belong. Do I now have to keep two objects for every firestore doc? The "real" one and a wrapper that keeps the relations?

Even if I have forward pointers on the collections, I don't think that puts me ahead. e.g.

Classrooms (collections)
    Room1 (doc)
        students: [ref to Billy.Jones.123, ...

I wouldn't query that classrooms' students with gets, because I got the whole collection in a students query. But I still need to turn the students array into an array of actual docs, not refs....

// ClientSideClassroom class constructor
this.students = this.doc.data().students.map(studentRef => {
  return // find the student in the studentsSnapshot with studentRef
})

Am I going about this all wrong?

Upvotes: 1

Views: 179

Answers (1)

Sculletbutt善
Sculletbutt善

Reputation: 460

Put all student name inside classA document. - you can get all student name on specific class. classCollection will have a lot doc such as classA, classB, classC

Put all family member name inside familyJones doc - you can get all family member name on one family doc

On user jones document, put all his detail such as class, family, school, home address inside one doc

This video will help u https://youtu.be/v_hR4K4auoQ

Upvotes: 1

Related Questions