When running my Android app using a Firebase Realtime Database I get the following warning:
Using an unspecified index. Consider adding ".indexOn" ... to your security and Firebase Database rules for better performance
I totally understand the warning. But I don't know how to make it better. I really want to query only on indexed fields!
This is my DB:
{
"groupUsers" : {
"g1" : {
"u1" : "admin"
},
"g2" : {
"u1" : "admin",
"u2" : "readonly"
}
},
"groups" : {
"g1" : {
"areas" : {
"a1" : {
"groupId" : "g1",
"name" : "My Group"
}
},
"interests" : {
"i1" : {
"groupId" : "g1",
"name" : "My Interest"
}
},
"points" : {
"p1" : {
"address" : "First Street",
"areaId" : "a1",
"groupId" : "g1",
"latitude" : -25,
"longitude" : -55,
"name" : "Harry"
}
},
"properties" : {
"name" : "My Group Name"
},
"waypoints" : {
"w1" : {
"areaId" : "a1",
"groupId" : "g1"
}
}
}
}
"users" : {
"u1" : {
"email" : "[email protected]",
"firstName" : "Peter",
"lastName" : "Smith"
},
"u2" : {
"email" : "[email protected]",
"firstName" : "John",
"lastName" : "Wayne"
}
}
}
These are my security rules:
{
"rules": {
"groups": {
"$groupId": {
".read": "root.child('groupUsers').child($groupId).child(auth.uid).exists()",
".write": "! root.child('groupUsers').child($groupId).exists() || root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin'",
"$child": {
".write": "root.child('groupUsers').child($groupId).child(auth.uid).exists() && root.child('groupUsers').child($groupId).child(auth.uid).val() !== 'readonly' && ($child === 'points' || $child === 'visits')"
}
},
"areas": {
".indexOn": ["groupId", "name"]
},
"waypoints": {
".indexOn": ["groupId", "areaId", "sequenceNumber"]
},
"interests": {
".indexOn": ["groupId", "rank", "name"]
},
"points": {
".indexOn": ["groupId", "areaId", "name"]
},
"visits": {
".indexOn": ["groupId", "pointId", "interestId", "userId"]
}
},
"users": {
".read": "auth != null",
"$userId": {
".write": "auth != null && $userId === auth.uid && newData.val() != null",
".indexOn": ["email", "firstName", "lastName"]
}
},
"groupUsers": {
".read": "auth != null",
"$groupId": {
".write": "auth != null && (root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin' || !root.child('groupUsers').child($groupId).exists())"
}
}
}
}
The problem is the groupUser
structure. It has group keys as property names. I do not have a field to index on since I do not have a constant property name.
How to change the structure to make it possible that all fields are indexed and that all my rules still work?
Tried getting your question, I got your point that you don't have key name to set index, As per documentation here we can use ".value"
here to add index on values,
Below might work for you, added .value
at user role level in groupUsers, as this seems to be only string value(user role) where you can set index
"groupUsers": {
".read": "auth != null",
"$groupId": {
".write": "auth != null && (root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin' || !root.child('groupUsers').child($groupId).exists())"
".indexOn": ".value"
}
}
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