The easiest way to understand why it is better to use a βflatterβ structure is to see how you protect it and how to implement the functionality.
Your first structure:
users: { uidOfJacob: { stackId: 884522, ssn: "999-99-9999", profile: { displayName: "Jacob Philips" } }, uidOfPuf: { stackId: 209103, ssn: "999-99-9999", profile: { displayName: "Frank van Puffelen" } } }
You would provide it with:
{ "rules": { "users": { "$uid": { ".read": "auth.uid == $uid", ".write": "auth.uid == $uid" "profile": { ".read": true } } } } }
One of the main reasons for having public information is to show a list of this information. In JavaScript:
ref.child('users').child(???).child('profile').on('child_added'...
This will not work because we put ??? . Firebase operations must be able to read the entire list from one place, and the user must have read permission at this entire location (and not just to individual child nodes).
If we structure the data to separate general information from private information, we get:
users: { uidOfJacob: { stackId: 884522, ssn: "999-99-9999", profile: { displayName: "Jacob Philips" } }, uidOfPuf: { stackId: 209103, ssn: "999-99-9999", profile: { displayName: "Frank van Puffelen" } } }, "profile": { uidOfJacob: { displayName: "Jacob Philips" }, uidOfPuf: { displayName: "Frank van Puffelen" } }
You would provide it with:
{ "rules": { "users": { "$uid": { ".read": "auth.uid == $uid", ".write": "auth.uid == $uid" } }, "profiles": { ".read": true, "$uid": { ".write": "auth.uid == $uid" } } } }
In order not to get a list of public user profiles, you should:
ref.child('profiles').on('child_added'...
This will work because everyone has read permission on profiles .