0

So suppose I am building an app that lets users manage trips. When a trip is created , any number of users can be added in it. I want this data to be stored in a single place and then for each user be able to retrieve the trips that that person is included in. My data looks like this:

-trips
  -<trip-id>
    -title
    -budget
    -etc
    -people
     -<person-id>
       -name
       -uid
     -<person-id>
       -name
       -uid
  -<trip-id>
       -
       -
       -
        

This trip will contain all the trips created by all the users. To show any person their trips, I want to retrieve only the lists that person exists in.

This is what I've tried to do including other similar approaches.

rootReference.child("trips").orderByChild("uid").equalTo(FirebaseAuth.instance.currentUser.uid).addValueEventListener(object:ValueEventListener){
override fun onDataChange(snapshot: DataSnapshot) {
   //this should only return the trips that current user exists in.
 }

}

I have checked the documentation for searching and filtering on firebase but there is nothing that show filtering based nested keys. One particular example is this. I understand it perfectly. If for example I try to filter my trips based on the main attributes like title, budget, it works, but not when I use an attribute of a nested child.

What other approach can I use to filter based to nested keys or should I structure the data differently? Any help is greatly appreciated.

Danish Ajaib
  • 83
  • 1
  • 3
  • 14

1 Answers1

1

Firebase Realtime Database queries operate on a flat list of child nodes directly under the path that you query.

So the value you order/filter on has to be at a fixex path under each immediate child node. Since that isn't the case for your uid, you can't query across all trips for the UID of all users of those trips.

You can query across one trip for a UID of a user (and then get back that user), or you can query across all trips for properties of the trip itself, such as its title or budget.

If you want to query across all users on all trips, consider keeping an additional list where you have the UID of the user as the key, and then all their trips under there:

"user_trips": {
  "uid1": {
    "tripid1": true,
    "tripid2": true
  },
  "uid2": {
    "tripid2": true,
    "tripid3": true
  }
}

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • This approach works in general but whats the best way to listen to the changes in all those trips collectively. I can get the trips based on the ids in 'user_trips' but then I am having to add a ValueEventListener for each of those trips individually which is not what I want. – Danish Ajaib Jan 22 '22 at 06:44
  • 1
    You could attach a listener to each trip ID you get back from the query, but if that number may be large (dozens is fine, hundreds may be a bit much), you'd end up with a lot of listeners. In such a situation, consider duplicating the data you need to detect the change in the `user_trips`, e.g. for example by storing the timestamp the trip was last updated as the value there. The writes become more complex again by doing so, but the query becomes simpler. That's a common trade-off when using NoSQL databases. – Frank van Puffelen Jan 22 '22 at 15:54