Search code examples
angularfirebasefirebase-realtime-databaseangularfire2

Query data in realtime database with AngularFire in nested structures


I have the following path in the Firebase Realtime database:

/dataTables/userId/dayDate/tableID/rowWithData

The structure of rowWithData is like this:

{
    "-NLBD8PD7i5DPfdgF": {
      "name": "Demo 1",
      "rows": {
        "-NLBD8RiJeyZpnKg8iKI": {
          "lastEdit": 1676495720665,
          "name": "Data 1",
          "priority": 1
        },
        "-NLBPODZMfFFXKTFDo7p": {
          "lastEdit": 1676495720665,
          "name": "Data 2",
          "priority": 5
        }
      }
  },
  "-NLBD8PD7asdas": {
    "name": "Demo 2",
    "rows": {
      "-NLBD8RiJeyZpnKg8iKI": {
        "lastEdit": 1676495720665,
        "name": "Data 3 here",
        "priority": 1
      },
      "-NLBPODZMfFFXKTFDo7p": {
        "lastEdit": 1676495720665,
        "name": "Data 4 here",
        "priority": 5
      }
    }
  }
}

I am trying these queries - the first one returns 0:

this.angularFireDatabase
  .list(`dataTables/${this.userInfo.uid}`, ref => ref.limitToFirst(50).equalTo(`search term`))
  .snapshotChanges()
  .subscribe(data => {
    console.log("search data", data);
  })   

The second one returns all the data from the database under this path /data/userId/dayDate:

this.angularFireDatabase
  .list(`dataTables/${this.userInfo.uid}`, ref => ref.orderByChild('rows'))
  .snapshotChanges()
  .subscribe(data => {
    console.log("search data", data);
    debugger;
  }) 

When I add the .equalsTo() function with any term it returns no results.

I am trying to search in the path /data/userId for all values that are in the search term.

Here are some info but I didn't find anything practical with my situation.

https://github.com/angular/angularfire/blob/master/docs/compat/rtdb/querying-lists.md

https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data


Solution

  • Filtering data in Firebase Realtime Database is a two-step process:

    1. First you order the data on a value by calling orderByKey, orderByValue, or orderByChild. This value has to be at a fixed path under each child node that is directly under the path that you query.
    2. Then then you can filter on the value you ordered on, for example with the equalTo operation.

    Since you don't call any orderBy, your node are ordered by their priority or key and none of those priorities/keys match the value you filter on.


    If you have a ref that points to root of the JSON you shared, you can filter on the name property with:

    ref.orderByChild("name").equalTo("Demo 1")
    

    This would give you a list with one resulting node; the -NLBD8PD7i5DPfdgF.


    If the ref variable points to the -NLBD8PD7i5DPfdgF in the JSON you shared, you can filter the rows of that specific node on their name property with:

    ref.child("rows").orderByChild("name").equalTo("Data 2")
    

    This would give you a list with a single resulting node again, the row with key -NLBPODZMfFFXKTFDo7p.


    There is no way to search across multiple properties for any of them to contain the value. If you need that, consider using a dedicated search engine rather than Firebase Realtime Database.


    There is no way to filter across the entire JSON for values in a specific row, as that no longer meets the requirement that the value to filter on exists on a fixed path under each direct child node.

    For more on that and possible solutions by changing the data model, see Firebase Query Double Nested and Firebase query if child of child contains a value