The Wrong Way
Consider the following structure
{
"users": {
// Uniquely generated IDs for children is common practice,
// it's actually really useful for automating child creation.
// Auto-incrementing an integer for a key can be problematic when a child is removed.
"-KH3Cx0KFvSQELIYZezv": {
"name": "Jon Snow",
"aboutMe": "I know nothing...",
"posts": {
"post1": {
"body": "Different roads sometimes leads to the same castle",
"isHidden": false
},
"post2": { ... },
// Possibly more posts
}
},
"-KH3Dx2KFdSLErIYZcgk": { ... }, // Another user
// A lot more users here
}
}
This is a great example of what NOT to do. Multi-nested structures such as the one above can be very problematic and could cause a huge performance setback.
The way Firebase accesses a node is by downloading all the children's data, then iterating over all same-level nodes (all parents' children). Now, imagine a database with several users, each having hundreds (or even thousands) of posts. Accessing a post in this case could potentially load hundreds of megabytes of unused data. In a more complicated application, the nesting could be deeper than just 4 layers, which would result in more useless downloads and iterations.
The Right Way
Flattening the same structure would look like this
{
// "users" should not contain any of the posts' data
"users": {
"-KH3Cx0KFvSQELIYZezv": {
"name": "Jon Snow",
"aboutMe": "I know nothing..."
},
"-KH3Dx2KFdSLErIYZcgk": { ... },
// More users
},
// Posts can be accessed provided a user key
"posts": {
"-KH3Cx0KFvSQELIYZezv": { // Jon Snow's posts
"post1": {
"body": "Different roads sometimes leads to the same castle",
"isHidden": false
},
"post2": { ... },
// Possibly more posts
},
"-KH3Dx2KFdSLErIYZcgk": { ... },
// other users' posts
}
}
This spares a huge amount of overhead by iterating over less nodes to access a target object. All users that do not have any posts would not exist in the posts branch, and so iterating over those users in the wrong way above is completely useless.