0

I'm creating a fitness app, and so far I came with the following structure:

Workout

  • difficulty (String)
  • duration (String)
  • exerciseSets (Firestore ref)

ExerciseSet

  • repNumber (int)
  • exercise (Firestore Ref)

and the Exercise object has a few fields describing the exercise.

So right now if i want to retrieve a whole workout, i need to do at least 3 calls to firestore, one for the Workout, then i get the ExerciseSets by ref (and there are usually a few in each workout) , and then the Exercise by ref as well..

ExerciseSet and Exercise objects are shared between workouts, thats why i have them in a different doc.

Also after retrieving all 3 or more snapshots from Firestore, i need to iterate through them to map it to my model.. i do something like this currently:

  for (var exerciseSet in fsWorkout.exerciseSets) {
    var fsExerciseSet = await _getFsExerciseSet(exerciseSet.ref);
    var set = ExerciseSet.fromFirstoreObject(fsExerciseSet);
    var fsExercise = await _getFsExercise(fsExerciseSet.exerciseRef.ref);
    set.exercise = Exercise.fromFirestoreObject(fsExercise);
    exerciseSets.add(set);
  }
  return Workout(fsWorkout.difficulty, fsWorkout.duration, exerciseSets);

Does this make sense? or is there a more efficient/easy way to achieve this? It feels like I over complicated stuff.. And is there any advantage to using firestore reference instead of just a String field with the ID? Thanks!

EDIT: I would like to mention that in my case all the data is added once by me, and the client reads the data and needs to retrieve a Workout object that contains all the ExerciseSet and Exercise objects.

1 Answer 1

1

You are actually applying an SQL normalization data-modelling strategy to a NonSQL database. This is not the most efficient approach...

In the NoSQL world, you should not be afraid to duplicate data and denormalize your data model. I would suggest your read this "famous" post about NoSQL data-modelling approaches.

So, instead of designing your data-model according to SQL normalization you should, in the NoSQL world, think about it from a query perspective, trying to minimize the number of queries for a given screen/use case.

In your case a common approach would be to use a set of Cloud Functions (which are executed in the back-end) to duplicate your data and have all the ExerciceSets and corresponding Exercises in your Workout Firestore document. And to keep all these data in sync, you would also use also use Cloud Functions.


You could also go for an intermediate approach where you only add the ExerciceSets data to a Workout and when the user wants to see an ExerciceSet details (e.g. by clicking on the ExerciceSet link) you query the corresponding Exercises.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer! So in my case all the workout data is read-only, that is added by me only once, and the clients reads this data. Would you suggest just adding all the duplicate data once and keep it that way? Also from what i've read the Cloud functions are a sort of middleware? to duplicate the data i would still have to query the db to get the object no?
Since you are the only one to edit the data and (if I understand correctly )it is done once and it doesn't change the answer is definitely yes, go for duplication. Cloud Functions are back-end code which is executed in serverless mode on Google/Firebase infrastructure: A bit like a middleware (or app server) that runs only when an event occurs. "to duplicate the data i would still have to query the db to get the object" => Yes, you would code the duplication.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.