DEV Community

Cover image for Build a Quiz REST API with NodeJS

Build a Quiz REST API with NodeJS

Carlos Magno on February 10, 2020

Hi there! Today we are going to build a simple Quiz REST API using NodeJS and MongoDB. It means people will be able to retrieve, update, delete and...
Collapse
 
mirceachirita profile image
mirceachirita

Many thanks man, great help and easy tutorial!

Collapse
 
raynerray profile image
RaynerRay

hi Carlos , how can one include images to the questions , like a question that has both text and image , thank you

Collapse
 
raymag profile image
Carlos Magno

Hello RaynerRay!
That's a interesting question. I'd suggest you to add a new string field in the question model (7th step of the tutorial). That way you can save the path or the link of the image in the database. It would be something like this (Note the "image" field):

const QuestionSchema = new mongoose.Schema({
    description: String,
    image: {
        type: String,
        required: false
    },
    alternatives: [
        {
            text: {
                type: String,
                required: true
            },
            isCorrect: {
                type: Boolean,
                required: true,
                default: false
            }
        }
    ]
})
Collapse
 
raynerray profile image
RaynerRay

Thanks mate, if it works, i'll post here

Collapse
 
raynerray profile image
RaynerRay

Hi Carlos , sorry man but have tried all i can it's not working, trying to store images in both questions and answers,for example so a question can have test question and image answers, please help 👏

Thread Thread
 
raymag profile image
Carlos Magno

Well, in order to add an image field for the question and for each alternative, you need to modify the model in Question.js. Here is my approach into this:

const QuestionSchema = new mongoose.Schema({
    description: String,
    image: {
        type: String,
        required: false
    },
    alternatives: [
        {
            text: {
                type: String,
                required: true
            },
            isCorrect: {
                type: Boolean,
                required: true,
                default: false
            },
            image: {
                type: String,
                required: false
            },
        }
    ]
})

Like I said before, you don't upload the images to the database, you just upload the link to the image, so they need to be hosted in another place on internet before hand.

Also, after modifying the model, you also need to update the routes for creating and updating questions in routes.js. Something like this:


// create one quiz question
router.post('/questions', async (req, res) => {
    try {
        const { description } = req.body
        const { image } = req.body
        const { alternatives } = req.body

        const question = await Question.create({
            description,
            alternatives,
            image
        })

        return res.status(201).json(question)
    } catch (error) {
        return res.status(500).json({"error":error})
    }
})

// update one quiz question
router.put('/questions/:id', async (req, res) => {
    try {
        const _id = req.params.id 
        const { description, image, alternatives } = req.body

        let question = await Question.findOne({_id})

        if(!question){
            question = await Question.create({
                description,
                alternatives
            })    
            return res.status(201).json(question)
        }else{
            question.description = description
            question.alternatives = alternatives
            question.image = image
            await question.save()
            return res.status(200).json(question)
        }
    } catch (error) {
        return res.status(500).json({"error":error})
    }
})
Thread Thread
 
raymag profile image
Carlos Magno

That way, when you are creating a new question, you can pass data like this:
creating a question

If you have more questions about this, feel free to send me a DM as well. Have a good day!

Thread Thread
 
raynerray profile image
RaynerRay

Many thanks, my mistake i was trying to upload images to the database, THANK YOU 🙏

Collapse
 
raynerray profile image
RaynerRay

Hi Carlos , another question , how can i create a relationship between the questions and a topic/subject, so that a user can select questions of a certain topic/subject only

Collapse
 
raymag profile image
Carlos Magno

Hey! Well, I see two ways of accomplishing that, one easy but not so good and another hard but a better solution.

The easy way is to just modify the Question model and add a "topic" field into it (it can either be a string or an array). The problem with that solution is that it can lead you to a lot of errors when registering new questions.

Now the second way is to create a model for the "topics" and modify the Question model with a new field for the "topics" (in this case, you would get the _id of the topic you want and save it inside the question). This way you can create new topics in the database and link them to the Questions.

It's kinda hard to explain how to do this with a comment, so I might write a new post to explain how you can build relationships between documents with mongodb as well. I hope I've been helpful.

Collapse
 
raynerray profile image
RaynerRay

true it's kinda hard to explain with a comment, maybe with code it'll be much clearer

Thread Thread
 
raynerray profile image
RaynerRay

I'm failing to direct you , want to show you my code, how can i dm you

Thread Thread
 
raymag profile image
Carlos Magno

I'm going to send you a message then.

Collapse
 
craig101 profile image
Craig Johnstone

Nice, look forward to the deployment tutorial!

Collapse
 
raymag profile image
Carlos Magno

Thanks Craig! I actually wrote a post about how to deploy an node API like this to Heroku for free, you might want to take a look.

Collapse
 
craig101 profile image
Craig Johnstone

Definitely will, thanks!

Collapse
 
kingluddite profile image
Pip

Great tutorial. Simple and to the point. Thanks!

Collapse
 
deleonmilleandrei3isc profile image
DeLeon-MilleAndrei-3ISC

Thanks you! Gave me an idea on train myself on Quiz parts. Anyhow, can I show you my code and guide me a little bit?
Would love to have your opinion on my project!

Collapse
 
raymag profile image
Carlos Magno

Hi! I'm sorry about taking so long to answer, I was out of the platform for a period. About your question, I'm always open to this. Feel free to email me.

Collapse
 
verbol_xyz profile image
Verbol • Edited

Great tutorial, many thanks from france !
I'm very impatient to read the following article about the front-end consumer !

Collapse
 
hetp97 profile image
Het Parekh

If we want to add more questions then what approach should be follow??

Collapse
 
raymag profile image
Carlos Magno

You can use the POST method for that, we have implemented it in one of the api routes (the 8th step).

Collapse
 
wali_ullah39 profile image
Wali Ullah

Informative and organized with good explanation. thanks brother

Collapse
 
rahulmishra117 profile image
Rahul Mishra

If I want to add any Link inside the Quiz option then How can I add it.

Collapse
 
raymag profile image
Carlos Magno

You mean a link inside the alternatives text? If so, you could add a new field for the links, or use something similar to markdown. Using markdown, you could properly render the link in the text in the front-end.

Collapse
 
aych_jayy profile image
H

Hi. I've been following your tutorial and have successfully completed it. Can you please post the frontend for this? I'm a beginner and would find that really helpful. Thanks

Collapse
 
aqeelsiddique profile image
Aqeel Siddique

same problem

Collapse
 
nahid570 profile image
Nahid Faraji

Thank you for your amazing tutorial.
Can you please tell me, how can I calculate points based on user answer. I will show a progressbar in frontend based on how much point earn by user.

Collapse
 
aqeelsiddique profile image
Aqeel Siddique

any one help me , how to make a handlebars file code of this Question schemma
Image description