Short question: Is it a bad practice in Firebase Realtime Database to run a transaction operation on a root node? (or any parent node with a lot of data.)
Long-ish version: Let's do an example based on a database structure recommended in the Firebase doc:
{
"users": {
// users indexed by their unique id
"alovelace": {
"name": "Ada Lovelace",
"groups": {
"techpioneers": true,
"womentechmakers": true
}
},
... // other users
},
"groups": {
// groups indexed by their unique id
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
... // other groups
}
}
Let's say I want to add a user to a group with runTransaction(). The only common shared node is the root, so I'll need to do something like:
runTransaction(ref(database, '/'), (value) => {
// do something with the data
})
To do this I need to have read access to the root node, which is kinda fine. As in, it's probably not doable from the client anymore, but you can rely on a Cloud Function or custom BE.
However, it seems like this is far from recommendable, as this operation requires downloading the whole database (or even a large portion of it in case you are not running the transaction on the root node, but still on some parent node with a lot of data).
So, what am I missing here? It seems that either I'm misunderstanding how runTransaction() works and why it requires read access, or it's a very unpractical method in real-life scenarios (also considering the best practices -presented by Firebase as well- on how to structure NoSQL databases).
Can somebody help me understand? thanks!
CodePudding user response:
Your understanding is correct: Firebase reads the entire node where a transactions runs, so you'll want to run it low in your JSON tree.
In the example you shared, adding a group doesn't require a transaction though, but can be accomplished with a single multi-path write operation:
firebase.database().ref().update({
"users/alovelace/groups/newGroup": true,
"groups/newGroup/members/alovelace": true
})