2

I am using the Firebase Realtime Database functions .orderByChild() and .equalTo() to fetch data nodes to be updated. However, I cannot seem to get any results back from my queries.

My database structure

{
  "4QEg0TWDbESiMX8Cu8cvUCm17so2" : {
    "-LmGtXsgJbAvVS8gv5-E" : {
      "createdAt" : 1565815876803,
      "message" : "Hello",
      "isSender" : false,
      "sender" : {
        "alias" : "",
        "name" : "Person A",
        "sid" : "mUO3DtYY2yRw3zkv4EmTlfldB3S2"
      },
      "sysStatus" : 0
    },
    "-LmGtt4nyuygG9B4s6__" : {
      "createdAt" : 1565815967746,
      "message" : "Hej!",
      "isSender" : true,
      "sender" : {
        "alias" : "",
        "name" : "Person B",
        "sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2"
      },
      "sysStatus" : 0
    },
    "-LmJxcvL_Y7JmojxPiiK" : {
      "createdAt" : 1565867281849,
      "isSender" : true,
      "message" : "111",
      "sender" : {
        "alias" : "",
        "name" : "Person B",
        "sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2"
      },
      "sysStatus" : 0
    }
  },
  "mUO3DtYY2yRw3zkv4EmTlfldB3S2" : {
    "222" : {
      "createdAt" : 1565867281849,
      "isSender" : true,
      "message" : "Test",
      "sender" : {
        "alias" : "",
        "name" : "Person A",
        "sid" : "mUO3DtYY2yRw3zkv4EmTlfldB3S2"
      },
      "sysStatus" : 0
    },
    "333" : { <-- This is one node I wish to fetch
      "createdAt" : 1565815967746,
      "isSender" : false,
      "message" : "123",
      "sender" : {
        "alias" : "",
        "name" : "Person B",
        "sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2" <-- This is the value I am trying to match
      },
      "sysStatus" : 0
    }
  },
  "rKNUGgdKqdP68T0ne6wmgJzcCE82" : {
    "-Lm_GTmNHyxqCqQl4D4Z" : { <-- This is one node I wish to fetch
      "createdAt" : 1566140917160,
      "isSender" : false,
      "message" : "Sesame",
      "sender" : {
        "alias" : "",
        "name" : "Person B",
        "sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2" <-- This is the value I am trying to match
      },
      "sysStatus" : 5
    }
  }
}
  

My code

dbRoot.child('messages')
.orderByChild('sid')
.equalTo(userId)
.once('value', (senderSnapshot) => {
  console.log('senderSnapshot', senderSnapshot.val())
  console.log('senderSnapshot amount', senderSnapshot.numChildren())
  senderSnapshot.forEach((sender)=>{
    //Do the work!
  })
})

The code logs

senderSnapshot null

senderSnapshot amount 0

I have manually checked that there are several nodes where "sid" is set to the "userId" I am looking for.

Why am I not getting any results back from my query?

It seems like I have to search dbRoot.child('messages/rKNUGgdKqdP68T0ne6wmgJzcCE82') to get my value. :/ (And then repeat the search for each user) How much extra data overhead would it be to download/collect all contacts and then loop thru each users contact?

Community
  • 1
  • 1
Kermit
  • 2,865
  • 3
  • 30
  • 53
  • If I had to guess this is because you are targeting nested properties, basically skipping messageId and sender properties. I don’t think orderByChild is recursive. You’d need to either use some sort of path with / or target a point in the tree that has access to sid directly. – Alexander Staroselsky Sep 06 '19 at 23:36
  • Instead of showing the database structure, edit your question to include the actual JSON (as text, no screenshots). You can get this by clicking the "Export JSON" link in the overflow menu (⠇) on your [Firebase Database console](https://console.firebase.google.com/project/_/database/data). – Frank van Puffelen Sep 07 '19 at 00:18
  • Hi @AlexanderStaroselsky! Thank you for the prompt reply! I am hoping you are wrong, I will perform some tests to find out. :) – Kermit Sep 07 '19 at 07:42
  • Hi @FrankvanPuffelen! Thank you for the reply! I have added the JSON representation of my database node. I hope it sheds some light on the issue. – Kermit Sep 07 '19 at 07:44
  • @AlexanderStaroselsky - You seem to be correct! When searching in dbRoot.child('messages/rKNUGgdKqdP68T0ne6wmgJzcCE82') I get a hit. Unfortunately this means I cannot rely on searches though. I will have to loop thru all data instead. – Kermit Sep 07 '19 at 08:15

1 Answers1

4

Firebase Database queries allow you to search through the direct child nodes at a certain location for a value at a fixed path under each child. So: if you know the user whose message you want to search through, you can do:

dbRoot
  .child('messages')
  .child('mUO3DtYY2yRw3zkv4EmTlfldB3S2') // the user ID
  .orderByChild('sender/sid')
  .equalTo(userId)

Note the two changes I made here from your code:

  1. We now start the search from messages/mUO3DtYY2yRw3zkv4EmTlfldB3S2, so that it only searches the messages for that one user.
  2. We now order/filter on the sender/sid property for each child under messages/mUO3DtYY2yRw3zkv4EmTlfldB3S2.

By combining these we are essentially searching a flat list of child nodes, for a specific matching value at a path under each child node.


There is no way in your current data structure to find all messages for a specific sender/sid value across all users. To allow that you'll have to add an additional data structure, where you essentially invert the current data.

"sender_messages": {
  "mUO3DtYY2yRw3zkv4EmTlfldB3S2": {
    "4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtXsgJbAvVS8gv5-E": true,
  },
  "4QEg0TWDbESiMX8Cu8cvUCm17so2": {
    "4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtXsgJbAvVS8gv5-E": true,
    "4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtt4nyuygG9B4s6__": true,
    "4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmJxcvL_Y7JmojxPiiK": true,
    "mUO3DtYY2yRw3zkv4EmTlfldB3S2/333": true,
    "rKNUGgdKqdP68T0ne6wmgJzcCE82/Lm_GTmNHyxqCqQl4D4Z": true
  },
  "mUO3DtYY2yRw3zkv4EmTlfldB3S2": {
    "mUO3DtYY2yRw3zkv4EmTlfldB3S2/222": true,
  }
}

Now you can find the messages for a specific sender/sid by reading:

dbRoot
  .child('sender_messages')
  .child('4QEg0TWDbESiMX8Cu8cvUCm17so2') // the sender ID

And then looping over the results, and loading the individual messages from each path as needed.

This is quite common in NoSQL databases: you'll often have to modify your data structure to allow the use-cases you want to add to your app.

See also:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807