0

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:

  1. Fetch all investments that belong to a particular user
  2. 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:

  1. 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 the if (initialDataLoaded) {} lines are executed?
  2. 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.

Espresso
  • 740
  • 13
  • 32

1 Answers1

0

Reading you post I can help you I think I can help you with a little information.

Regarding the first question that you ask, about if you can guarantee that the code in the child_added's call back it would be executed before the code in he values' call back. The response will be it depends, depends in the code that you put in each call back one maybe it would take longer than the other but it would depend.

Regarding the second question you can check this page that will help you to pinpoint exactly what reference (including children) was hogging the bandwidth and check that part of the code it's taking that much bandwidth.

And for the last question you might be able to use Firebase.ServerValue.TIMESTAMP with a filter for users, but after looking for a while it could be a little complicated to implement, maybe the easier solution would be to use Cloud Firestore since handle more complex queries as you say.

Robertocd_98
  • 404
  • 2
  • 8