2

I am having an issue querying on nested data from Firebase Realtime Database.

Given the following example data structure:

"crossing":
        "1346":
            "data1": "value"
            "data2": "value"
            "projectName": "PN-1"
        "1562":
            "data1": "value"
            "data2": "value"
            "projectName": "PN-1"
        "1933":
            "data1": "value"
            "data2": "value"
            "projectName": "PN-2"

Let us assume that this collection will have hundreds of children. Also, the ID is random and unknown before the execution time of the query. Every crossing has several other values as you can see in the picture.

At first, I had to list all the crossings whose key starts with the given value. So, for example, if I search for '1', I would like to get all the crossings in this simple example.

This code snippet solves this problem. Although, I am still not sure if this is the best way to achieve this.

firebase
  .database()
  .ref("crossing")
  .orderByKey()
  .startAt(self.searchedKey)
  .endAt(self.searchedKey + "\uf8ff")
  .once("value", function(snapshot) {
    if (snapshot.val()) {
      console.log(snapshot.val());
    }
  });

My main problem is, that now I have to list all the crossings whose projectName value starts with the given value.

However, I cannot compose the proper query for that. I cannot use the .orderByChild() function, since the children keys (the IDs), are unknown.

I cannot afford to query all the crossings from the collection and iterate over all the elements on the frontend side since later this object will be huge with lots of crossings. As I see some kind of order is still a must.

gemboly
  • 63
  • 1
  • 6
  • I'm not sure I understand correctly. Why are you trying to filter by key? And what else are you trying to filter on? – Frank van Puffelen Mar 23 '20 at 17:33
  • Because these keys will be some kind of serial numbers of the crossings. Users should query for specific serial numbers in order to get more details of them. Also, of course they will know the registered IDs. – gemboly Mar 23 '20 at 17:38

1 Answers1

1

Firebase Realtime Database can only order/filter on one value from each child node. That can either be the key of each nodes (orderByKey()), its value (orderByValue()), or the value of a single property at a known path under each node (orderByChild("path/to/property")). You can use any of these, but only of of them for any query.

If you want to filter on multiple properties (as an AND) it often is possible to combine the values you want to filter on into a single (synthetic) property. For example, you could (also) add the key of each node in a property and combine it with the project name into: "projectName_key": "PN-1_ 1346" and then order/filter on that property.

For a longer example of this and other approaches, see my answer here: Query based on multiple where clauses in Firebase

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