I have some data in a Firebase Realtime Database that looks as follows:
users: {
$user1: {
email: "person@gmail.com"
name: "Bob"
},
$user2: {
email: "otherperson@gmail.com"
name: "Sally"
},
...
}
investments: {
$investment1: {
user: $user1,
ticker: "GOOG",
name: "Google Inc",
...
},
$investment2: {
user: $user1,
ticker: "AAPL",
name: "Apple Inc",
...
},
$investment3: {
user: $user2,
ticker: "TSLA",
name: "Tesla Inc",
...
},
...
}
Where $user1
represents the id of user1 (generated by firebase).
In my web application, I would like to:
- Fetch all investments that belong to a particular user
- Then, listen for any newly added investments that belong to that user
The reason I want to fetch all of the existing investments at the same time is so my application doesn't re-render for each time the child_added listener callback is called.
For a small number of investments, the following code should work fine.
const userId = "..."; // userId of logged in user
let initialDataLoaded = false;
// For newly added investments
database
.ref("investments")
.orderByChild("user")
.equalTo(userId)
.on("child_added", (snapshot) => {
if (initialDataLoaded) {
const newlyAddedInvestment = snapshot.val();
/* add new row to table */
}
});
// For existing investments
database
.ref("investments")
.orderByChild(userId)
.equalTo(userId)
.once("value", (snapshot) => {
const existingInvestments = snapshot.val();
/* display existing investments in a table */
initialDataLoaded = true;
});
}, []);
However, I am worried about what would happen if a user had a large number of existing investments. Particularly, I am worried about two things:
- The child_added callback will be called for every existing investment. I know firebase guarantees that child_added events are triggered before value events, but can it guarantee that the code inside the child_added callback is executed before the code inside the value event callback is executed? If not, then isn't it possible that
initialDataLoaded
is set to true before all of theif (initialDataLoaded) {}
lines are executed? - The child_added callback will be called for every existing investment. This could chew up a lot of bandwith.
I read in another SO post that I could add a createdAt
timestamp to all of the investments, and then use a ref.orderByChild('createdAt').startAt(Firebase.ServerValue.TIMESTAMP);
query to only fetch newly added investments. I like this solution as it scales to large datasets, however, since I am already ordering by user
, I don't believe I can use this method (please correct me if I am wrong). If there is a way to retrieve only the users investments that also start after Firebase.ServerValue.TIMESTAMP
this would also answer my question. If this is a limitation of Realtime Database, I might try out Cloud Firestore since I know that it supports more complex queries, which would solve this problem.
I might be overthinking this, but I want to get a reliable solution that doesn't cause unecessary re-renders and does not cause unecessary event triggers.