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!
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.
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 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.
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.
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"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With