DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Consuming GraphQL API With React.js
  • What Is Grafbase?
  • What Is GraphQL?
  • Pagination in GraphQL: Efficiently Retrieve and Manipulate Data

Trending

  • The End of “Good Enough Agile”
  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • GitHub Copilot's New AI Coding Agent Saves Developers Time – And Requires Their Oversight
  • Scaling Microservices With Docker and Kubernetes on Production
  1. DZone
  2. Data Engineering
  3. Databases
  4. Create a Book Rating System With the Goodreads API and Slash GraphQL

Create a Book Rating System With the Goodreads API and Slash GraphQL

In this article, we'll be building an e-commerce bookstore that relies on Slash GraphQL. Find out more!

By 
Michael Bogan user avatar
Michael Bogan
DZone Core CORE ·
Updated Jan. 21, 21 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
19.9K Views

Join the DZone community and get the full member experience.

Join For Free

GraphQL is a relatively new way to build user interfaces and APIs for consumers. It's essentially a querying language backed by a strongly typed schema, making it easy to write human-readable requests to get exactly the data you need. Compared to REST, whose responses are dictated by the server, GraphQL queries place the power squarely in the client's hands.

However, GraphQL is really just a spec that describes an API. Many features one might expect from an API, like authorization/authentication logic, bi-directional communication, or rate-limiting, still need to be implemented. Recently launched, Slash GraphQL is a fully managed GraphQL backend that takes care of all the hard work of setting up a GraphQL API, letting you concentrate on building your app.

In this article, we'll be building an e-commerce bookstore that relies on Slash GraphQL. To demonstrate the service's flexibility, we'll also be fetching data from another source — the Goodreads API — and integrate it into our responses.

We'll be building our app using Node.js, so you should have at least version 12 installed on your machine. Create a directory called slashql_bookstore and navigate into it from the command line.

Creating the GraphQL Backend

Setting Up Slash GraphQL

Setting up an account on Slash GraphQL is easy — you can instantly sign-in with your GitHub account. The platform has a free trial you can use for this walkthrough. 

interactive tutorial

After you've created an account, you'll need to create a new backend:

1. Click on "Launch a New Backend."

2. Name the backend "Bookstore."

3. Click "Launch."

That's it! You now have a server spun up for you in an AWS region.

Defining the GraphQL Schema

Every GraphQL server has a strongly typed schema, which defines the objects and fields available to consumers.

Click on "Schema" and paste the following lines:

Plain Text
 




xxxxxxxxxx
1
23


 
1
type Book {
2
  id: Int!
3
  isbn: Int!
4
  title: String! @search(by: [fulltext])
5
  author: Author!
6
}
7

          
8
type Author {
9
  id: Int!
10
  firstname: String!
11
  lastname: String!
12
}


Here we've defined two types — 'Book' and 'Author' — representing the data in our API. Slash GraphQL provides support for custom directives is one of the most convenient of its many niceties. Here, for example, by annotating the 'title' field with @search, we can provide a fuzzy text with no additional work.

Click "Deploy" to send this schema to production.

Setting Up the Data

Let's move on to inserting data. We can use the API Explorer not only to add data but query it, too. To populate our GraphQL backend, we'll define a list of books and their authors through a mutation that Slash GraphQL conveniently provides for us, based on our schema:

Plain Text
 




xxxxxxxxxx
1
23


 
1
mutation AddData {
2
  addBook(input: [
3
    {id: 1, title: "The Sound and The Fury", isbn: 9780394747743, author: {id:1, firstname: "William", lastname: "Faulkner"}},
4
    {id: 2, title: "Light in August", isbn: 9780394711898, author: {id:1, firstname: "William", lastname: "Faulkner"}},
5
    {id: 3, title: "Giovanni's Room", isbn: 9780141032948, author: {id:2, firstname: "James", lastname: "Baldwin"}},
6
    {id: 4, title: "The Fire Next Time", isbn: 9780140182750, author: {id:2, firstname: "James", lastname: "Baldwin"}},
7
    {id: 5, title: "To The Lighthouse", isbn: 9780140274165, author: {id:3, firstname: "Virginia", lastname: "Woolf"}},
8
    {id: 6, title: "Orlando", isbn: 9780241284643, author: {id:3, firstname: "Virginia", lastname: "Woolf"}}
9
    ]) {
10
  numUids
11
  }
12
}


Click the giant Play button to have this data added to the backend. 

request headers

Now, let's run a query to verify that this data is present:

Java
 




xxxxxxxxxx
1
19


 
1
query GetBooks {
2
  queryBook {
3
    title
4
    isbn
5
    author {
6
      firstname
7
      lastname
8
    }
9
  }
10
}


You should see a response back that shows all of the data you previously inserted. 

Building the Server

We'll now use Express to set up a basic API server to provide users access to this Slash GraphQL source. Our Express server acts as little more than an interface to hand requests off to Slash GraphQL. Its most important lines are these:

JavaScript
 




x
34


 
1
const BACKEND_URL = "https://rampant-arm.us-west-2.aws.cloud.dgraph.io/graphql"
2

          
3
async function fetchGraphQL(operationsDoc, variables) {
4
  const result = await axios({
5
    method: 'POST',
6
    url: BACKEND_URL,
7
    headers: {
8
      'Content-Type': 'application/json',
9
    },
10
    data: JSON.stringify({
11
      query: operationsDoc,
12
      variables,
13
    }),
14
  })
15
  return result.data
16
}
17

          
18
const query = `
19
query {
20
  queryBook {
21
    title
22
    isbn
23
    author {
24
      firstname
25
      lastname
26
    }
27
  }
28
}
29

          
30
`
31
app.get('/', jsonParser, async (req, res) => {
32
  let gqlResponseData = await fetchGraphQL(query,  {})
33
  res.render('index', { books: gqlResponseData.data.queryBook })
34
})


Here, we've defined a helper function, fetchGraphQL, which sets up the necessary headers and data to send over to Slash GraphQL. Keep in mind that you'll need to change BACKEND_URL to match the URL that Slash GraphQL gives you. Then, we write a GraphQL query that defines the data that we want. Finally, we set up a route to fetch that data and then render it in our view:

HTML
 




xxxxxxxxxx
1
23


 
1
<div class="container">
2
  {{#each books}}
3
  <div class="row">
4
    <div class="col-md-4">
5
      <h2>{{title}}</h2>
6
      <h4>{{author.firstname}} {{author.lastname}}</h4>
7
      <p><strong>ISBN:</strong> {{isbn}}</p>
8
    </div>
9
  </div>
10
  <hr>
11
  {{/each}}
12
</div>


Our view is backed by Handlebars, which is a popular templating library. We can feed our JSON data into an HTML fragment and iterate over the keys and values, making it much easier to display the information. Here we're using an #each loop to go over every book returned by the GraphQL API and then plugging the data into HTML tags. You'll notice that we have placeholders that match the names of the JSON keys; these are replaced by the real data when the page is viewed.

After you npm install all the dependencies, run the server with node server.js. Then, head on over to localhost:3000 in your browser: 

welcome to the bookstore

You should get back the same response that Slash GraphQL's API Explorer gave.

Extend the Server

As a final step, we want to expose some reviewer data about these books. But we don't want to create dummy data here; instead, we'll use the Goodreads API. Make sure you set up an account there and get an API key before continuing.

One of the many things that Slash GraphQL excels at is stitching together disparate sources of data into one GraphQL interface. Perhaps you'll want to make calls to other API endpoints that are under your control. To support this, Slash GraphQL provides the @custom directive, which allows you to implement custom behavior for GraphQL fields and resolvers.

First, let's add our rating information to the existing schema:

Plain Text
 




xxxxxxxxxx
1


 
1
type Rating @remote {
2
  ratings_count: Int!
3
  average_rating: Float!
4
}


Our Rating type defines field names which we expect from the book.show_by_isbn API. We don't need to define every field that their REST API provides, only the ones we're interested in. Slash GraphQL will know how to transform that response into a GraphQL one.

On the field side of things, we'll need to specify the URL we want to call out to, along with the HTTP method:

Java
 




xxxxxxxxxx
1


 
1
type Book {
2
  # ...
3
  rating: Rating @custom(http: {
4
  url: "https://goodreads-api-munger.glitch.me?isbn=$isbn",
5
  method: GET
6
  })
7
  # ...
8
}


You'll notice here that we're actually calling out to a Glitch project. The Goodreads API doesn't return JSON data in a nice, neat format. We'll call out to an intermediary server that will munge the data into a more legible format. This server's details aren't all that important (but you can check it out if you want to). It is important to note that this URL can stand in for anything, which can be super helpful if you're interacting with data that you own.

The other amazing thing is that Slash GraphQL will substitute data for you. See that part of the URL that says $isbn? Depending on the object returned by our query, Slash GraphQL will substitute in the real field value for that variable. This keeps your URL requests flexible and easy to manage.

That's all that we need to do to bring in some custom data. Our GraphQL query can now add this rating field to bring in that external data. Let's replace the query in our server.js with this one:

Plain Text
xxxxxxxxxx
1
16
 
1
const query = `
2
query {
3
  queryBook {
4
    title
5
    isbn
6
    rating {
7
      ratings_count
8
      average_rating
9
    }
10
    author {
11
      firstname
12
      lastname
13
    }
14
  }
15
}
16
`
4
    title

And, let's update the view to show this information:

HTML
 




xxxxxxxxxx
1
25


 
1
<div class="container">
2
  {{#each books}}
3
    <div class="row">
4
      <div class="col-md-4">
5
      <h2>{{title}}</h2>
6
      <h4>{{author.firstname}} {{author.lastname}}</h4>
7
      <p><strong>ISBN:</strong> {{isbn}}</p>
8
      <p>Rating: {{rating.average_rating}} (out of {{rating.ratings_count}} votes)</p>
9
    </div>
10
  </div>
11
  <hr>
12
  {{/each}}
13
</div>


If you restart the server and head back to localhost:3000, you should now see the ratings populated as well:

welcome to the bookstore

Conclusion

Slash GraphQL makes it incredibly easy to set up a production-grade GraphQL API, but we've only scratched the surface. In addition to combining disparate data locations, it also supports authorization, subscriptions, and even encryption.

You can grab the complete source code for this tutorial over at GitHub. If you haven’t already, be sure to sign up for Slash GraphQL — feel free to share your creations with the rest of the Dgraph community.

API GraphQL Data (computing) Book

Opinions expressed by DZone contributors are their own.

Related

  • Consuming GraphQL API With React.js
  • What Is Grafbase?
  • What Is GraphQL?
  • Pagination in GraphQL: Efficiently Retrieve and Manipulate Data

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!