1

I'm building out a messaging application with the following hierarchy:

Organization -> Chat Rooms -> Threads -> Messages

I'm a little confused as to the best approach to structure the relational entities in firebase. The docs say flatten your data, but if the data is flattened then each record must be searched in order to find the identifiers, which seems more costly. What is the most cost-efficient or "proper" way of doing this? Below is my original proposal. The arrows denote a parent->child relationship. The underscores below id means a generated identifier (using firebase .push()).

rooms ->
  _room_id ->
    org_id
    label
    created
    type

threads ->
  _thread_id ->
    room_id
    created

messages ->
  _message_id ->
    thread_id
    user_id
    name
    created
    status
    body

And here's the newly proposed structure. The primary difference between these two is how the relational entities sit at the child level rather than the parent.

rooms ->
  org_id ->
    _room_id ->
      label
      created
      type


threads ->
  org_id ->
    room_id ->
      _thread_id ->
        created

messages ->
  org_id ->
    room_id ->
      thread_id ->
        _message_id ->
          user_id
          created
          status
          body

With the newly proposed structure, the uri structure could look something like this:

/rooms/<org_id>                          -> rooms
/threads/<org_id>/<room_id>              -> threads
/messages/<org_id>/<room_id>/<thread_id> -> messages

Appreciate any insights on the best approach. Thanks

Community
  • 1
  • 1
  • The answer really depends on how the user interacts with the data. For example; assuming you have users logged in, the app they are using would be observing the messages node for new messages. When a new message is posted, their app would be notified of it, and based on the above structure the org_id, room_id, thread_id etc. So there would be no need to 'search in order to find identifier' since it's delivered when you are notified of the new message. – Jay May 24 '15 at 11:01
  • If you need to search for a users message(s) the first structure makes the most sense with maybe one change; if you know the message_id, you can directly access the thread_id node and likewise the room_id node as well as which user it is. If you need to load which messages a user posted, you may want to consider a users node that contains the message_id's of the messages the user posted - that could be done via code in your app as well. – Jay May 24 '15 at 11:20
  • Firebase opens a single web socket and then performs all reads/writes over that connection. So after the initial connection, the reads/writes are a lot faster than you're probably used to. But if you need to join multiple "tables" together for every screen, you're probably modeling a bit too close to SQL still. I prefer denormalizing a bit more and making the main screens close to a single read operation (at the cost of some data duplication): http://stackoverflow.com/questions/16638660/firebase-data-structure-and-url/16651115#16651115 – Frank van Puffelen May 24 '15 at 23:00
  • But as Jay said: "the best" almost always depends on your exact use-cases, which only you can answer. – Frank van Puffelen May 24 '15 at 23:01
  • Thanks for the feedback! I've found that firebase security & rules only will allow you to only show or hide data based on your conditional states -- there's no way to filter out what data is returned. This implies that you need to go the route of either nesting your objects like my second proposal above, or creating some sort of index table to return a list of your identifiers... unless I'm missing something obvious? – user2150618 May 25 '15 at 03:36
  • You can certainly filter data using a query. However it's a little different than an SQL query and only goes 1 level deep. That's why I had suggested adding a users node containing each user_id with message_id's being each users children. You could then query for a specific user_id on the users node, which would then return all of that users message_id's. Once you have those you could query the messages node for data for that specific message or query for a group of messages. Also, the security & rules define the read & write requirements of firebase nodes, they do not show or hide data. – Jay May 25 '15 at 18:05
  • Just another clarification; in general you would query for data when you need to read in 'records' that have some common value; e.g. all messages that contain the word 'wonky'. In Firebase you use Observe to be notified when 'records' in a specific node have been added, edited or removed and Firebase provides those 'records' for you to process (e.g. any message that was just added or any message that was just edited) – Jay May 25 '15 at 18:21

0 Answers0