Kermit
Kermit

Reputation: 3417

Firebase Realtime Database - Best practice for additional data nodes (lookups and initial load)

I have a Firebase Realtime Database with the below structure.

I wish to fetch all "notes" a user has access to and, initially, only show titles for the notes.

notes: {
  "noteId-1345" : {
    "access" : {
      "author": "1234567890"
        "members": {
          "1234567890": 0 <--- Author
          "0987654321": 1 <--- Member
        }
      },
    "data" : {
      "title": "Hello",
      "content": "Konichiwa!",
      "comment": "123"
    }
  }
}

To be able to fetch all notes a user has access to I have expanded my data model by keeping an additional user_notes node in the root: Whenever I associate a user (update of members) with a note, I write that relation both in /notes/$noteid and in /user_notes/$uid.

user_notes: {
  "$uid": {
    "noteId-1345": true
  }
}

When fetching initial data I only need the "notes" the user has access to - including titles.

(I only fetch the entire "note" if a user wants to view a complete "note")

I begin by fetching the ids for notes the user has access to and then I have to do another lookup to fetch the titles.

let titles = []
database.ref(`user_notes/${uid}`)
.on('value', (snaps) => {
  snaps.forEach((snap) => {
    const noteId = snap.key
    database.ref(`notes/${noteId}/data/title`).on('value', (noteSnap) => {
      const title = noteSnap.val()
      titles.push(title)
    }
  })
})

Is this the most efficient approach? - It seems inefficient to do double lookups.

Should I store title, and other data needed for initial load, in the user_notes node as well to avoid double lookups?

What is considered to be best practice in cases like this when using a NoSQL database?

Kind regards /K

Upvotes: 0

Views: 79

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600006

What you're doing is indeed the common approach. It is not nearly as slow as you may initially think, since Firebase pipelines the requests over a single connection.

A few things to consider:

  • I'd typically move the members for each note under a top-level node note_members. Separating the types of data typically makes it much easier to keep your security rules reasonable, and is documented under keep your data structure flat.

  • If you'd like to get rid of the lookup, you can consider storing the title of each note under each user_notes node where you have the ID. You'd essentially replace the true with the name:

    user_notes: {
      "$uid": {
        "noteId-1345": "Hello"
      }
    }
    

    This simplifies the lookup code (its main advantage) and makes it a bit faster.

    This sort of data duplication is quite common when using Firebase and other NoSQL databases, you trade write complexity and extra data storage, for reach simplicity and scalability.

Upvotes: 1

Related Questions