Reputation: 171
I am struggling with an optimal schema for my app. Should I go with top level collections, sub-collections, arrays, etc.
Setup:
Requirements:
Any help is appreciated.
Upvotes: 2
Views: 691
Reputation: 4465
I think start with the basics, and hopefully there's cohesion throughout. Each following part seems to work on its own, you may find that together it makes sense to keep some things within documents rather than their own collection, or to maintain sub-collections rather than root collections, etc.:
You can consider nesting the questions within quizzes, but you may wish to keep them root level so you can easily reuse questions for multiple quizzes.
So may be worth keeping an array in each question's document for which quizzes that question belongs to.
You can then perform a query like this to get all questions for a quiz:
db.collection('questions').where('quizzes','array-contains', quizId)
That would get you all questions for each quiz and satisfy your 2nd req (and 1st is already satisfied).
The questions would come with their potential answers, which I think should each be given their own id. Like this:
-- question1
----- "Do you xyz?"
----- potentialAnswers
--------- { id: xyz123, answer: "Yes" }
--------- { id: wxy456, answer: "No" }
What this allows you to do is take each answer a user gives, and query to see if that exists as a match in your answers database.
I like this so far because it allows you to query for all questions and you get all potential answers in one query/one organized list. You can rearrange the potential answers when you display them, so "C" in each display of multiple choice does not need to always be the same "C." As long as the ID is a match when you go to compare, you're solid.
That comparison may look like this:
db.collection('answers').where('questionId','==', 'question1').where('answerId', '==', 'xyz123')
If you get a doc returned with a query like this, they've answered correctly.
For every answer a user gives, I would mark it in a sub-collection of each user, where the quizId is the ID of the document. So under user1, they'll have a collection called quizzes.
As a user answers, you can push to a map within that user's quiz document the answer they gave. This might look like this:
-- user1
----- quizzes
-------- quiz1
----------- progress: 2/25
----------- complete: true
----------- score: 1/2
----------- answers
-------------- { questionId: question1, answer: xyz123, correct: true }
-------------- { questionId: question2, answer: rst456, correct: false }
For every quiz you want the user to take, as long as no document with that quizID lives in {userID}/quizzes} with complete=true, they can start it, or continue taking it, etc.
This is more than most people get, so hope it's helpful. Some things may need to be fleshed out a bit more and others may have differing opinions, but I like these exercises.
Upvotes: 5