Reputation: 901
I have a data path like this
events
-KntTJCVBtbrb79dHemC
dateStamp: 1498747689858
admin: "rPxwIzEtJaRbEH6ujkP5QJgpHDp2"
attending:
rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true
MtaPwHEKMEOTXBRdXBuXuS3gst12: false
I would like to get the events that have certain users attending. In other words, I would like to get all events where the key "attending/[some-user-id]" exists.
Problem is I have only been able to do it by filtering by a specific value of that path (either true or false), like this:
eventsRef.orderByChild("attending/" + user.getId()).equalTo(true).addListenerForSingleValueEvent(...)
That works but only for where the value of the key is true, so to get what I need I have to do 2 calls, one for when the value is true and one for when it is false.
I tried using startAt(true) and endAt(false) (and viceversa) but that ended up returning nothing.
I'm not sure what I am missing.
EDIT
I should have specified that I know this could be done with denormalization and using another node as the relationship 'table', I was just wondering if the above specifically was possible since it is already so close and it would avoid a 2-step process of getting a key first and then retrieving the actual data.
Upvotes: 0
Views: 324
Reputation: 2396
Here's when denormalisation of data comes into play!
What you described is the only method to query a grandchild. And of course, as you mentioned, it is not very intuitive, useful or fast.
What you have to do is to create a separate node for the users attending a given event. You can name it something like UsersAttendingTheEvent
. This will have the event keys as children. Whenever a user starts attending a given event, add the user key as a child of the event key ( and thus, grandchild of UsersAttendingTheEvent
.
So, for example,
UsersAttendingTheEvent:{
-KntTJCVBtbrb79dHemC:{
rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true
MtaPwHEKMEOTXBRdXBuXuS3gst12: false
}}
Now, when you want to run a query, you can just run a simple orderByChild(userId)
query on UsersAttendingTheEvent
to obtain all the keys of the events that the user is attending.
Following this, you can obtain the Event details from your main event/eventKey
. This might seem like an additional call, but it is how denormalisation of data is designed for Firebase. Plus, it works reasonably fast.
EDIT
The reason your startAt(true
) and endAt(false)
returned nothing is that when orderByChild()
is called, the order in which the items returned are as follows:-
This is mentioned on this page https://firebase.google.com/docs/database/android/lists-of-data.
Try using only startAt(true)
. This would work if you make sure that your member keys only have true or false values and no other value would be returned lexicographically after true
.
Upvotes: 2