Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding and ".indexOn": ".value" into Firebase Rules

I'm studying AngularJS and Firebase and I'm playing with a simple ChatApp, just to understand the code.

My Firebase DB structure is like this:

"chat": {
    "messages": {
        "chat1": { [ list of messages ] },
        "chat2": { [ list of messages ] }
    },
    "rooms": {
        "chat1": {
            "users": {
                "user1": true,
                "user2": true
            }
        },
        "chat2": {
            "users": {
                "user2": true,
                "user3": true
            }
        }
    }
}

Due to Firebase protection Rules I can't add chat link in the user node, than I necessary have to do a Firebase query to retrieve chat rooms for user, using orderByChild() query on App Start Up.

Using Firebase is simple than I can retrieve all chat using:

var chatLink = firebase.database().ref('chat/rooms');
chatLink
  .orderByChild('users/' + userId)
  .equalTo(true)
  .once('value', function(chatSnap){

      /* Do Some Stuff Here */

  });

Every thing work well, but I'm receiving a warning in the console:

FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "users/{userId}" at /chat/rooms to your security rules for better performance

Searching on the web, I found that for variable orderByChild() query, I can user .indexOn: .value in my Firebase Rules.

I've tried to add this Rule:

{
    "rules": {
        "chat": {
            "rooms": {
                ".indexOn": ".value"
            }
        }
    }
}

But I'm still receive always that warning. How can i fix it?

Thank you very much!

like image 811
Marco Cavanna Avatar asked Apr 06 '17 16:04

Marco Cavanna


People also ask

How do I modify Firebase rules?

Edit and update your rulesOpen the Firebase console and select your project. Then, select Realtime Database, Cloud Firestore or Storage from the product navigation, then click Rules to navigate to the Rules editor. Edit your rules directly in the editor.

How do I add and retrieve data from Firebase?

Inside Firebase in the Data tab, you are getting to see the below screen. Hover your cursor on null and click on the “+” option on the right side and click on that option. After clicking on that option. Add the data as added in the below image.

How do you secure Firebase rules?

How do they work? Firebase Security Rules work by matching a pattern against database paths, and then applying custom conditions to allow access to data at those paths. All Rules across Firebase products have a path-matching component and a conditional statement allowing read or write access.


2 Answers

To index this structure to allow efficient querying, you have to add an index for each user:

{
    "rules": {
        "chat": {
            "rooms": {
                ".indexOn": ["users/user1", "users/user2"]
            }
        }
    }
}

That won't be maintainable, since you're likely adding users dynamically.

As usual with NoSQL databases, this means you have to expand/adapt your data model to allow the use-case you want. Instead of querying the rooms for their users, keep a list of the rooms for each user (in addition to your current data):

"user_rooms": {
  "user1": {
    "chat1": true
  },
  "user2": {
    "chat1": true,
    "chat2": true
  }
  "user3": {
    "chat2": true
  }

Now you can look up the chat rooms for a user without even needing to query.

Also see my answer about this categorization problem in Firebase query if child of child contains a value.

like image 197
Frank van Puffelen Avatar answered Sep 18 '22 05:09

Frank van Puffelen


I am aware that this may be a bit too late but here is something that may help you. I was looking for the same information as you, and in my case, it helped me.

$usersId matches any child key. So you have to do something like this.

{
"rules": {
      "chat": {
          "rooms": {
              "users": {
                  "$usersId": {
                    ".indexOn": ".value"
                }
            }
        }
    }
}

My case:

Using an unspecified index. Consider adding ".indexOn": "date" at messages/-L2bPVX4_fL41H7lhexc to your security and Firebase Database rules for better performance:

L2bPVX4_fL41H7lhexc == child in my NoSQL database structure

solution:

"messages": {
  "$messagesId": {
    ".indexOn": "date"
  }
}
like image 31
DawidJ Avatar answered Sep 20 '22 05:09

DawidJ