0

I'm trying to increase performance in my Firebase Realtime database by creating indices by following recommendations in the console log. Most recommendations are easy to follow, but not all.

My existing rule:

"notes": {
  ".indexOn": ["data/title", "access/author"],
  ".read": "
    auth.uid !== null 
  ",
  "$note_id": {
    ".write": "
      (!data.exists() && auth.uid !== null) ||
      (
        data.child('access').child('author').val() === auth.uid 
      ||
        data.child('access/members').child(auth.uid).exists()
      )
    ",
    "data": {
      ".read": "
        data.parent().child('access').child('author').val() === auth.uid ||
        data.parent().child('access/members').child(auth.uid).exists()
      ",
      ".write": "
        data.parent().child('access').child('author').val() === auth.uid ||
        data.parent().child('access/members').child(auth.uid).exists()          
      ",
    "access" : {
      ".read" : "
        (auth.uid !== null) &&
        (
          data.child('author').val() === auth.uid
          ||
          data.child('members').child(auth.uid).exists()
        )
      ",
    "members" :{
        ".write" : "
          (!data.exists() && auth.uid !== null) ||
          data.parent().child('author').val() === auth.uid ||
          data.parent().child(auth.uid).exists()
        "
      }
    }
  }
},

Some recommendations are for locations that end with the users uid - similar to the below console log:

FIREBASE WARNING: Using an unspecified index.

Consider adding ".indexOn": "access/members/3weT1tYhG456HH0CuC45Muc44ax6" at /notes to your security rules for better performance

Can this index rule be added in Firebase Realtime Database - considering the location locations is ending with user uid string?

1 Answer 1

1

Your current data structure makes it easy to find the members for a specific note. It does not make it easy to find the notes for a specific member. To allow that second use-case and ensure it is scalable, you'll want to add an additional data structure:

user_notes: {
  user_id_1: {
    note_id1: true,
    note_id2: true,
    note_id3: true
  },
  user_id_2: {
    note_id3: true,
    note_id4: true,
    note_id5: true
  }
}

With this additional structure you can determine what nodes a user has access to without needing a query.

This of course means you need to write to two locations when you allow a user access to a note, but this is quite common and scalable, and can still be secured with rules.

Also see:

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @frank for the prompt reply and great answer! :) That seems like a simple enough solution. I already have database listeners in place to do the work. Now I am just wondering how I would go about fetching those notes (not just the id) in a effective manner?
By the way - would you recommend writing data simultaneously (atomic) from the client to update the user_notes node or using a database listener?
Fetching the actual nodes with the above structure means you'll use a once() listener for each. That is not nearly as slow as you may initially think, since Firebase pipelines the requests over a single connection. You could also write the entire note in both places of course, which would duplicate data but make the reads simpler and a bit faster.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.