I'd like to start using Firebase as my main BaaS now that Parse is closing. At the moment, Firebase's real-time capabilities are interesting and I see using them in the future, but for now I'd primarily like to use Firebase as a way to store a User and there associated data. With Parse, this was super easy, which required only uploading an object with the associated user attached to the object. I could then filter by the objects which were associated with that user.
However, in Firebase everything is Event driven as opposed to on-demand and you can't filter by security rules. In general, I like this approach, but I'm having trouble applying it to what I need today. I don't have much of background in networking/databases, so its possible some of this stuff is really basic.
Here is what I'm looking to do:
My Firebase data structure looks like this currently:
xnterval
users
100b920f-d2c5-4578-9f49-ecf38ef71302
32a8dbf2-009a-44c5-a188-ca2c280ba135
d53b0b37-d773-4cf5-af94-74635fc76f1f
name: "Joe Schmo"
provider: "password"
username: "jschmo"
workouts
-K9wZ4_Rt-xBdVZt93d4
workout_id: "-K9wZ4_Rt-xBdVZt93d3"
workouts
-K9wZ4_Rt-xBdVZt93d3
interval_period: 180
intervals: 2
name: "Workout"
owner: "d53b0b37-d773-4cf5-af94-74635fc76f1f"
rest_period: 150
work_period: 30
Inside the User/"uid" I have a workouts list which is order by childByAutoId and contains the ID of a single workout.
What I want to be able to do, is get a list of all the user's workouts and then retrieve that complete workout list from the workouts section.
I know the PATH directly to the users workouts root/"uid"/workouts, but how would I retrieve the entire list and get each "workout_id" and then subsequently query for that list of workouts in the /workouts section?
I've also already setup Security rules such that no other user can access another users data, and the only user that can read/write a workout is if the owner of that workout is the UID on the authenticated user. This I do have working correctly.
Maybe I'm going about this the wrong way, or there is an easier way to structure my data to accomplish what I want. I read a few articles on de-normalizing your data in order to optimize the amount of transfer required in a query, and building for the future I feel like this data structure is ideal for that. But if you have more experience, please let me know. Thanks!
Update
So I've create this method which will retrieve all the user's workout ID's and store them into an array userWorkoutIds:
private func observeAllUserWorkouts() {
if userAuthData != nil {
workoutObserver = userRef?.childByAppendingPath("workouts").observeEventType(FEventType.Value, withBlock: { snapshot in
let enumerator = snapshot.children
while let child = enumerator.nextObject() as? FDataSnapshot {
NSLog("\(child.childSnapshotForPath("workout_id").value)")
self.userWorkoutIds?.append(child.childSnapshotForPath("workout_id").value as! String)
}
})
}
}
Now that I know exactly the paths of all the users workouts /workouts/"IDs", how can I poll for all of them at once as opposed to setting up single shot observers for all the different paths? OR is that the only option?
A super quick solution: add the uid of the user to the workout_id node.
Then you can query on the workouts node for uid equal to the user of whose workouts you want to retrieve.
workouts
workout_id_0
interval_period: 180
internvals: 2
uid: user_id
workout_id_1
interval_period: 180
internvals: 2
uid: user_id
A second option:
If you know the path to the user workouts
/users/uid_id/workouts
you could observe the node by value, which would read in all of the children in that node into a snapshot. Then iterate over the snapshot to get specific data. I personally would load each item in the snapshot into an array of dictionaries or maybe even workout object.