building the polls API with Hasura GraphQL Engine

Let's quickly build the polls api with Hasura GraphQL Engine

we already know the concept of polls app(i.e It consists of questions and choices and people choses the choice for a specific question). Let’s build an api for polls app using Hasura GraphQL Engine

We have already seen how to setup the Hasura GraphQL Engine. If you do not know how to set it up the read our article “Instant GraphQL API for Postgres with Hasura” and get back here.

What api’s we will be building ?

  • An api to create a poll question.
  • Api to list questions.
  • Api to get question detail.
  • Api to edit a question.
  • Api to delete a question.
  • Api to create choice for a particular question.
  • Api to see question detail along with available choices.
  • Api to vote for a particular choice of a question.

Database Schema

Let’s create the database schema for polls api. We have two tables 1. Question 2. Choice

Table: Question

Question table has the fields id, question_text, pub_date.

Hasura GraphQL Polls API

Table: Choice

Choice table has the fields id, question_id, choice_text, votes.

Hasura GraphQL Polls API

Create a poll question

GraphQL mutation to insert the data

mutation CreateQuestion{
  insert_question_one(object: {
    question_text: "What is python?", pub_date: "2020-05-05"
  }){
    id
    question_text
    pub_date
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'x-hasura-admin-secret: hasurasecret' --data '{"query":"mutation CreateQuestion{\n  insert_question_one(object: {\n    question_text: \"What is python?\", pub_date: \"2020-05-05\"\n  }){\n    id\n    question_text\n    pub_date\n  }\n}","variables":null,"operationName":"CreateQuestion"}'

Output:

{
  "data": {
    "insert_question_one": {
      "id": 1,
      "question_text": "What is python?",
      "pub_date": "2020-05-05"
    }
  }
}

List all poll questions

Graphql query to retrieve all questions

query AllQuestions {
  question{
    id
    question_text
    pub_date
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'Referer: http://localhost:4400/console/api-explorer' -H 'content-type: application/json' -H 'x-hasura-admin-secret: hasurasecret' -H 'Origin: http://localhost:4400' --data '{"query":"query AllQuestions {\n  question{\n    id\n    question_text\n    pub_date\n  }\n}","variables":null,"operationName":"AllQuestions"}'

Output:

{
  "data": {
    "question": [
      {
        "id": 1,
        "question_text": "What is python?",
        "pub_date": "2020-05-05"
      }
    ]
  }
}

Retrieve a specific poll question

Graphql query to retrieve a specific question with pk

query RetrieveQuestionWithPK {
  question_by_pk(id: 1) {
    id
    question_text
    pub_date
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'content-type: application/json' -H 'x-hasura-admin-secret: hasurasecret' -H 'Origin: http://localhost:4400' -H 'Connection: keep-alive' --data '{"query":"query RetrieveQuestionWithPK {\n  question_by_pk(id: 1) {\n    id\n    question_text\n    pub_date\n  }\n}\n","variables":null,"operationName":"RetrieveQuestionWithPK"}'

Output:

{
  "data": {
    "question_by_pk": {
      "id": 1,
      "question_text": "What is python?",
      "pub_date": "2020-05-05"
    }
  }
}

Edit a poll question

Graphql mutation to update a specific question

mutation UpdateQuestionWithPK {
  update_question_by_pk(pk_columns: {id: 1}, _set: {question_text: "Who invented python?"}) {
    id
    pub_date
    question_text
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'content-type: application/json' -H 'x-hasura-admin-secret: hasurasecret' -H 'Origin: http://localhost:4400' -H 'Connection: keep-alive' --data '{"query":"mutation UpdateQuestionWithPK {\n  update_question_by_pk(pk_columns: {id: 1}, _set: {question_text: \"Who invented python?\"}) {\n    id\n    pub_date\n    question_text\n  }\n}\n","variables":null,"operationName":"UpdateQuestionWithPK"}'

Output:

{
  "data": {
    "update_question_by_pk": {
      "id": 1,
      "pub_date": "2020-05-05",
      "question_text": "Who invented python?"
    }
  }
}

If you see that we have updated the question text from What is python? to Who invented python?.

Delete a poll question

GraphQL mutation to query to delete the question with pk

mutation DeleteQuestionByPK{
  delete_question_by_pk(id: 1) {
    id
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'content-type: application/json' -H 'x-hasura-admin-secret: hasurasecret' --data '{"query":"mutation DeleteQuestionByPK{\n  delete_question_by_pk(id: 1) {\n    id\n  }\n}\n","variables":null,"operationName":"DeleteQuestionByPK"}'

Output:

{
  "data": {
    "delete_question_by_pk": {
      "id": 1
    }
  }
}

Let’s insert the question back again with the query

mutation CreateQuestion{
  insert_question_one(object: {
    question_text: "What is python?", pub_date: "2020-05-05"
  }){
    id
    question_text
    pub_date
  }
}

Output:

{
  "data": {
    "insert_question_one": {
      "id": 2,
      "question_text": "What is python?",
      "pub_date": "2020-05-05"
    }
  }
}

Create choices for the question

Graphql mutation query to create question choices in bulk

mutation CreateChoices {
  insert_choice(objects: [
    {choice_text: "snake", question_id: 2, votes: 0},
    {choice_text: "programming language", question_id: 2, votes: 0},
    {choice_text: "both", question_id: 2, votes: 0},
    {choice_text: "I don't know", question_id: 2, votes: 0}]) {
    returning {
      choice_text
      id
      question_id
      votes
    }
  }
}

cURL:

curl 'http://localhost:4400/v1/graphql' -H 'content-type: application/json' -H 'x-hasura-admin-secret: hasurasecret' --data $'{"query":"mutation CreateChoices {\\n  insert_choice(objects: [\\n    {choice_text: \\"snake\\", question_id: 2, votes: 0},\\n    {choice_text: \\"programming language\\", question_id: 2, votes: 0},\\n    {choice_text: \\"both\\", question_id: 2, votes: 0},\\n    {choice_text: \\"I don\'t know\\", question_id: 2, votes: 0}]) {\\n    returning {\\n      choice_text\\n      id\\n      question_id\\n      votes\\n    }\\n  }\\n}\\n","variables":null,"operationName":"CreateChoices"}'

Output:

{
  "data": {
    "insert_choice": {
      "returning": [
        {
          "choice_text": "snake",
          "id": 2,
          "question_id": 2,
          "votes": 0
        },
        {
          "choice_text": "programming language",
          "id": 3,
          "question_id": 2,
          "votes": 0
        },
        {
          "choice_text": "both",
          "id": 4,
          "question_id": 2,
          "votes": 0
        },
        {
          "choice_text": "I don't know",
          "id": 5,
          "question_id": 2,
          "votes": 0
        }
      ]
    }
  }
}

Question detail with choices

Before getting the question detail with choices we need to configure the Relationships like below as show in the image.

Hasura GraphQL relationships

Now, we are ready to query the GraphQL. Let’s do that

GraphQL query

query GetQuestion {
  question{
    id
    question_text
    pub_date
    choices{
      id
      choice_text
      votes
    }
  }
}

Output:

{
  "data": {
    "question": [
      {
        "id": 2,
        "question_text": "What is python?",
        "pub_date": "2020-05-05",
        "choices": [
          {
            "id": 2,
            "choice_text": "snake",
            "votes": 0
          },
          {
            "id": 3,
            "choice_text": "programming language",
            "votes": 0
          },
          {
            "id": 4,
            "choice_text": "both",
            "votes": 0
          },
          {
            "id": 5,
            "choice_text": "I don't know",
            "votes": 0
          }
        ]
      }
    ]
  }
}

Whoa! Yes, we got the question details with all of the choices.

Vote for a choice

Graphql mutation query to update the choice

mutation {
  update_choice(_inc: {votes: 1}, where: {id: {_eq: 2}}) {
    returning {
      choice_text
      id
      question_id
      votes
    }
  }
}

I’m sure you are now comfortable with cURL so, I’m just skipping the cURL. Try it out on your own this time.

Output:

{
  "data": {
    "update_choice": {
      "returning": [
        {
          "choice_text": "snake",
          "id": 2,
          "question_id": 2,
          "votes": 1
        }
      ]
    }
  }
}

We have upvoted the choice with id 2. If you observe we have created the choice with votes 0. After the above query it incremented it by 1. Because we have sent _inc: {votes: 1} in the query.

Let’s do the question detail query again to see if the votes updated or not.

query GetQuestion {
  question{
    id
    question_text
    pub_date
    choices{
      id
      choice_text
      votes
    }
  }
}

Output:

{
  "data": {
    "question": [
      {
        "id": 2,
        "question_text": "What is python?",
        "pub_date": "2020-05-05",
        "choices": [
          {
            "id": 3,
            "choice_text": "programming language",
            "votes": 0
          },
          {
            "id": 4,
            "choice_text": "both",
            "votes": 0
          },
          {
            "id": 5,
            "choice_text": "I don't know",
            "votes": 0
          },
          {
            "id": 2,
            "choice_text": "snake",
            "votes": 1
          }
        ]
      }
    ]
  }
}

If we see the above output the choice with id 2 has votes 1 and other choices votes are 0. So, we have completed the apis for the polls app using Hasura GraphQL Engine.

It’s that simple to create the GraphQL api’s using Hasura. That’s it folks. Let’s do more in the coming articles!

Thank you for reading the Agiliq blog. This article was written by Anjaneyulu Batta on May 4, 2020 in GraphQLPostgreSQL .

You can subscribe ⚛ to our blog.

We love building amazing apps for web and mobile for our clients. If you are looking for development help, contact us today ✉.

Would you like to download 10+ free Django and Python books? Get them here