{"id":62537,"date":"2019-03-28T04:19:50","date_gmt":"2019-03-28T11:19:50","guid":{"rendered":"http:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/"},"modified":"2019-03-28T04:19:50","modified_gmt":"2019-03-28T11:19:50","slug":"building-real-time-charts-with-graphql-and-postgres","status":"publish","type":"post","link":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/","title":{"rendered":"Building Real-Time Charts With GraphQL And Postgres"},"content":{"rendered":"<link rel=\"canonical\" href=\"https:\/\/www.smashingmagazine.com\/2019\/03\/realtime-charts-graphql-postgres\/\"><title>Building Real-Time Charts With GraphQL And Postgres<\/title><\/p>\n<article>\n<header>\n<h1>Building Real-Time Charts With GraphQL And Postgres<\/h1>\n<address>Rishichandra Wawhal<\/address>\n<p>                  <time datetime=\"2019-03-27T13:00:08+01:00\">2019-03-27T13:00:08+01:00<\/time><time datetime=\"2019-03-28T11:06:14+00:00\">2019-03-28T11:06:14+00:00<\/time><\/header>\n<p>Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients we work with.<\/p>\n<p>Why are real-time charts so important? Well, they\u2019re useful in cases when new data is produced continuously; for example, when using live-time series for visualizing stock prices is a great use for real-time charts. In this tutorial, I\u2019ll explain how to build real-time charts with open-source technologies apt for exactly this particular task.<\/p>\n<p><strong>Note<\/strong>: <em>This tutorial requires basic knowledge of React and GraphQL.<\/em><\/p>\n<h4>Stack<\/h4>\n<ol>\n<li><a href=\"https:\/\/www.postgresql.org\/\">PostgreSQL<\/a><br \/>\nThe very point behind using Charts is to visualize \u201chuge\u201d volumes data. We, therefore, need a database that efficiently handles large data and provides an intuitive API to restructure it. SQL databases allow us to make views that abstract and aggregate data for us. We will be using Postgres which is a <a href=\"https:\/\/www.postgresql.org\/docs\/9.2\/history.html\">time-tested<\/a> and highly efficient database. It also has fancy open-source extensions like <a href=\"https:\/\/www.timescale.com\/\">Timescale<\/a> and <a href=\"https:\/\/postgis.net\/\">PostGIS<\/a> which allow us to build geolocation-based and time-series-based charts respectively. We will be using Timescale for building our time series chart.<\/li>\n<li><a href=\"https:\/\/hasura.io\/\">GraphQL Engine<\/a><br \/>\nThis post is about building real-time charts, and GraphQL comes with a well-defined spec for real-time subscriptions. Hasura GraphQL Engine is an <a href=\"https:\/\/github.com\/hasura\/graphql-engine\">open-source<\/a> GraphQL server that takes a Postgres connection and allows you to query the Postgres data over realtime GraphQL. It also comes with an access control layer that helps you restrict your data based on custom access control rules.<\/li>\n<li><a href=\"https:\/\/www.chartjs.org\/\">ChartJS<\/a><br \/>\nChartJS is a popular and well maintained open source library for building charts with JavaScript. We will use <code>chart.js<\/code> along with its ReactJS abstraction <code>react-chartjs-2<\/code>. About why React, it is because React empowers developers with an intuitive event-driven API. Also, React\u2019s unidirectional data flow is ideal for building charts that are data-driven.<\/li>\n<\/ol>\n<div data-component=\"FeaturePanel\" data-audience=\"non-subscriber\" data-remove=\"true\"><\/div>\n<h4>Requirements<\/h4>\n<p>For this tutorial, you will need the following on your system:<\/p>\n<ol>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/articles\/www.docker.com\">Docker CE<\/a><br \/>\nDocker is a software that lets you containerize your applications. A docker image is an independent packet that contains software along with its dependencies and a minimalistic operating system. Such docker images can be technically run in any machine that has docker installed. You will need docker for this tutorial.<\/p>\n<ul>\n<li><a href=\"https:\/\/www.docker.com\/get-started\">Read more about Docker<\/a><\/li>\n<li><a href=\"https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/\">Install Docker<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/articles\/www.npmjs.com\">npm<\/a>: npm is the package manage for JavaScript.<\/li>\n<\/ol>\n<h4>Demo<\/h4>\n<p>We will build the following live time series chart that shows the maximum temperature of a location in intervals of 5 seconds over the past 20 minutes from the present moment.<\/p>\n<figure><img data-src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-demo.gif\" alt=\"GIF Demo of the realtime chart\"><figcaption>GIF Demo of the realtime chart<\/figcaption><\/figure>\n<h3>Setting Up The Backend<\/h3>\n<h4>Running The Services<\/h4>\n<p>The backend comprises of a Postgres database, its timescale extension, and Hasura GraphQL Engine. Let us get the database and our GraphQL server running by running the respective docker images. Create a file called <code>docker-compose.yaml<\/code> and paste this content into it.<\/p>\n<p><strong>Note<\/strong>: <code>docker-compose<\/code> <em>is a utility to run multiple docker images declaratively.<\/em><\/p>\n<div>\n<pre><code>version: '2'\nservices:\n  timescale:\n    image: timescale\/timescaledb:latest-pg10\n    restart: always\n    environment:\n      POSTGRES_PASSWORD: postgrespassword\n    volumes:\n    - db_data:\/var\/lib\/postgresql\/data\n  graphql-engine:\n    image: hasura\/graphql-engine:v1.0.0-alpha38\n    ports:\n    - \"8080:8080\"\n    depends_on:\n    - \"timescale\"\n    restart: always\n    environment:\n      HASURA_GRAPHQL_DATABASE_URL: postgres:\/\/postgres:postgrespassword@timescale:5432\/postgres\n      HASURA_GRAPHQL_ACCESS_KEY: mylongsecretkey\n    command:\n      - graphql-engine\n      - serve\n      - --enable-console\nvolumes:\n  db_data:\n<\/code><\/pre>\n<\/div>\n<p>This <code>docker-compose.yaml<\/code> contains the spec for two services:<\/p>\n<ol>\n<li><code>timescale<\/code><br \/>\nThis is our Postgres database with Timescale extension installed. It is configured to run at port 5432.<\/li>\n<li><code>graphql-engine<\/code><br \/>\nThis is our Hasura GraphQL Engine instance, i.e. the GraphQL server that points to the database and gives GraphQL APIs over it. It is configured to run at the port 8080, and the port 8080 is mapped to the port 8080 of the machine that this docker container runs on. This means that you can access this GraphQL server through at <code>localhost:8080<\/code> of the machine.<\/li>\n<\/ol>\n<p>Let\u2019s run these docker containers by running the following command wherever you have placed your <code>docker-compose.yaml<\/code>.<\/p>\n<pre><code>docker-compose up -d\n<\/code><\/pre>\n<p>This command pulls the docker images from the cloud and runs them in the given order. It might take a few seconds based on your internet speed. Once it is complete, you can access your GraphQL Engine console at <code>http:\/\/localhost:8080\/console<\/code>.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png?ssl=1\"><br \/>\n\t\t<img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-console-landing.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-console-landing.png?w=900\" sizes=\"100vw\" alt=\"Hasura GraphQL Engine Console\"><\/a><figcaption>\n\t\t\tHasura GraphQL Engine console (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0a1baeaf-4b1b-40e2-932b-5efe334e9eda\/realtime-charts-graphql-postgres-console-landing.png\">Large preview<\/a>)<br \/>\n\t\t<\/figcaption><\/figure>\n<h4>Setting Up The Database<\/h4>\n<p>Next, let us create a table called temperature that stores the values of temperatures at different times. Go to the Data tab in the console and go to the <code>SQL<\/code> section. Create our <code>temperature<\/code> table by running this SQL block:<\/p>\n<pre><code>CREATE TABLE temperature (\n  temperature numeric not null,\n  location text not null,\n  recorded_at timestamptz not null default now()\n);\n<\/code><\/pre>\n<p>This creates a simple Postgres table in the database. But we wish to leverage the time interval partitioning of the Timescale extension. To do this, we must convert this table into timescale\u2019s hypertable by running the SQL command:<\/p>\n<pre><code>SELECT create_hypertable('temperature', 'recorded_at');\n<\/code><\/pre>\n<p>This command creates a hypertable that is partitioned by time in the field <code>recorded_at<\/code>.<\/p>\n<p>Now, since this table is created, we can directly start making GraphQL queries over it. You can try them out by clicking on the <code>GraphiQL<\/code> tab on top. Try making a mutation first:<\/p>\n<pre><code>mutation {\n  insert_temperature (\n    objects: [{\n      temperature: 13.4\n      location: \"London\"\n    }]\n  ) {\n    returning {\n      recorded_at\n      temperature\n    }\n  }\n}\n<\/code><\/pre>\n<p>The GraphQL mutation above inserts a row in the <code>temperature<\/code> table. Now try to make a GraphQL query to check if the data was inserted.<\/p>\n<p>Then try making a query:<\/p>\n<pre><code>query {\n  temperature {\n    recorded_at\n    temperature\n    location\n  }\n}\n<\/code><\/pre>\n<p>Hope it worked :)<\/p>\n<p>Now, the task at our hand is to create a live time-series chart that shows the maximum temperature of a location in intervals of 5 seconds over the past 20 minutes from the present moment. Let\u2019s create a view that gives us exactly this data.<\/p>\n<pre><code>CREATE VIEW last_20_min_temp AS (\n  SELECT time_bucket('5 seconds', recorded_at) AS five_sec_interval,\n  location,     \n    MAX(temperature) AS max_temp\n  FROM temperature\n  WHERE recorded_at > NOW() - interval '20 minutes'    \n  GROUP BY five_sec_interval, location    \n  ORDER BY five_sec_interval ASC\n);\n<\/code><\/pre>\n<p>This view groups the data from the <code>temperature<\/code> table in 5-second windows with their max temperature (<code>max_temp)<\/code>. The secondary grouping is done using the <code>location<\/code> field. All this data is only from the past twenty minutes from the present moment.<\/p>\n<p>That\u2019s it. Our backend is set up. Let us now build a nice real-time chart.<\/p>\n<div><\/div>\n<h3>Frontend<\/h3>\n<h4>Hello GraphQL Subscriptions<\/h4>\n<p>GraphQL subscriptions are essentially \u201clive\u201d GraphQL queries. They operate over WebSockets and have exactly the same response structure like GraphQL queries. Go back to <code>http:\/\/localhost:8080\/console<\/code> and try to make a GraphQL subscription to the view we created.<\/p>\n<pre><code>subscription {\n  last_20_min_temp(\n    order_by: {\n      five_sec_interval: asc\n    }\n    where: {\n      location: {\n        _eq: \"London\"\n      }\n    }\n  ) {\n    five_sec_interval\n    location\n    max_temp\n  }\n}\n<\/code><\/pre>\n<p>This subscription subscribes to the data in the view where the location is <code>London<\/code> and it is ordered in ascending order of the <code>five_second_intervals<\/code>.<\/p>\n<p>Naturally, the response from the view would be an empty array because we have not inserted anything in the database in the past twenty minutes. (You might see the entry that we inserted sometime back if you reached this section within twenty minutes.)<\/p>\n<pre><code>{\n  \"data\": {\n    \"last_20_min_temp\": []\n  }\n}\n<\/code><\/pre>\n<p>Keeping this subscription on, open another tab and try inserting another value in the <code>temperatures<\/code> table using the same mutation that we performed earlier. After inserting, if you go back to the tab where the subscription was on, you would see the response having updated automatically. That\u2019s the realtime magic that GraphQL Engine provides. Let\u2019s use this subscription to power our real-time chart.<\/p>\n<h4>Getting Started With Create-React-App<\/h4>\n<p>Let us quickly get started with a React app starter using <a href=\"https:\/\/github.com\/facebook\/create-react-app\">create react app<\/a>. Run the command:<\/p>\n<pre><code>npx create-react-app time-series-chart\n<\/code><\/pre>\n<p>This will create an empty starter project. <code>cd<\/code> into it and install the GraphQL and chart libraries. Also, install <a href=\"https:\/\/momentjs.com\/\">moment<\/a> for converting timestamps to a human-readable format.<\/p>\n<div>\n<pre><code>cd time-series-chart\nnpm install --save apollo-boost apollo-link-ws subscriptions-transport-ws graphql react-apollo chart.js react-chartjs-2 moment\n<\/code><\/pre>\n<\/div>\n<p>Finally, run the app with <code>npm start<\/code> and a basic React app would open up at <code>http:\/\/localhost:3000<\/code>.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png?ssl=1\"><br \/>\n\t\t<img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-create-react-app-start.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-create-react-app-start.png?w=900\" sizes=\"100vw\" alt=\"Raw create-react-app\"><\/a><figcaption>\n\t\t\tRaw creat-react-app (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a9f1db83-c44a-4857-8029-a2819ee51663\/realtime-charts-graphql-postgres-create-react-app-start.png\">Large preview<\/a>)<br \/>\n\t\t<\/figcaption><\/figure>\n<h4>Setting Up Apollo Client For Client-Side GraphQL<\/h4>\n<p><a href=\"https:\/\/www.apollographql.com\/docs\/react\/\">Apollo client<\/a> is currently the best GraphQL client that works with any GraphQL compliant server. Relay modern is good too but the server must support the relay spec to leverage all the benefits of Relay modern. We\u2019ll use Apollo client for client-side GraphQL for this tutorial. Let us perform the setup to provide Apollo client to the app.<\/p>\n<p>I am not getting into the subtleties of this setup because the following code snippets are <a href=\"https:\/\/www.apollographql.com\/docs\/react\/advanced\/subscriptions.html#subscriptions-client\">taken directly from the docs<\/a>. Head to <code>src\/index.js<\/code> in the React app directory and instantiate Apollo client and add this code snippet above <code>ReactDOM.render<\/code>.<\/p>\n<pre><code>import { WebSocketLink } from 'apollo-link-ws';\nimport { ApolloClient } from 'apollo-client';\nimport { ApolloProvider } from 'react-apollo';\nimport { InMemoryCache } from 'apollo-cache-inmemory';\n\n\/\/ Create a WebSocket link:\nconst link = new WebSocketLink({\n  uri: 'ws:\/\/localhost:8080\/v1alpha1\/graphql',\n  options: {\n    reconnect: true\n  }\n});\nconst cache = new InMemoryCache();\nconst client = new ApolloClient({\n  link,\n  cache\n});\n<\/code><\/pre>\n<p>Finally, wrap the <code>App<\/code> inside <code>ApolloProvider<\/code> so that we can use Apollo client in the children components. Your <code>App.js<\/code> should finally look like:<\/p>\n<pre><code>import React from 'react';\nimport ReactDOM from 'react-dom';\nimport '.\/index.css';\nimport App from '.\/App';\nimport { WebSocketLink } from 'apollo-link-ws';\nimport { ApolloClient } from 'apollo-client';\nimport { ApolloProvider } from 'react-apollo';\nimport { InMemoryCache } from 'apollo-cache-inmemory';\n\n\/\/ Create a WebSocket link:\nconst link = new WebSocketLink({\n  uri: `ws:\/\/localhost:8080\/v1alpha1\/graphql`,\n  options: {\n    reconnect: true\n  }\n});\nconst cache = new InMemoryCache();\nconst client = new ApolloClient({\n  link,\n  cache\n});\n\nReactDOM.render(\n  (\n    <ApolloProvider client={client}> \n      <App \/>\n    <\/ApolloProvider>\n  ),\n  document.getElementById('root')\n);\n<\/code><\/pre>\n<p>Apollo client has been set up. We can now easily use real-time GraphQL from our App. Head to <code>src\/App.js<\/code>.<\/p>\n<div><\/div>\n<h4>Building The Chart<\/h4>\n<p>ChartJS provides a pretty neat API for building charts. We will be building a line chart; so a line chart expects data of the form:<\/p>\n<pre><code>{\n  \"labels\": [\"label1\", \"label2\", \"label3\", \"label4\"],\n  \"datasets\": [{\n    \"label\": \"Sample dataset\",\n    \"data\": [45, 23, 56, 55],\n    \"pointBackgroundColor\": [\"red\", \"brown\", \"green\", \"yellow\"],\n    \"borderColor\": \"brown\",\n    \"fill\": false\n  }],\n}\n<\/code><\/pre>\n<p>If the above dataset is used for rendering a line chart, it would look something like this:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png?ssl=1\"><br \/>\n\t\t<img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-line-chart-sample.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-line-chart-sample.png?w=900\" sizes=\"100vw\" alt=\"Sample line chart\"><\/a><figcaption>\n\t\t\tSample line chart (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a3e7b9bf-129d-44c7-9f32-dd1b2af0129f\/realtime-charts-graphql-postgres-line-chart-sample.png\">Large preview<\/a>)<br \/>\n\t\t<\/figcaption><\/figure>\n<p>Let us try to build this sample chart first. Import <code>Line<\/code> from <code>react-chartjs-2<\/code> and render it passing the above object as a data prop. The render method would look something like:<\/p>\n<div>\n<pre><code>render() {\n  const data = {\n    \"labels\": [\"label1\", \"label2\", \"label3\", \"label4\"],\n    \"datasets\": [{\n      \"label\": \"Sample dataset\",\n      \"data\": [45, 23, 56, 55],\n      \"pointBackgroundColor\": [\"red\", \"brown\", \"green\", \"yellow\"],\n      \"borderColor\": \"brown\",\n      \"fill\": false\n    }],\n  }\n  return (\n    <div\n      style={{display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '20px'}}\n    >\n      <Line\n        data={data}\n      \/>\n    <\/div>\n  );\n}\n<\/code><\/pre>\n<\/div>\n<p>Next, we will subscribe to the data in our view and feed it to the Line chart. But how do we perform subscriptions on the client?<\/p>\n<p><a href=\"https:\/\/www.apollographql.com\/docs\/react\/advanced\/subscriptions.html#subscription-component\">Apollo\u2019s <code><Subscription><\/code> components<\/a> work using the <a href=\"https:\/\/reactjs.org\/docs\/render-props.html\">render prop<\/a> pattern where the children of a component are rendered with the context of the subscription data.<\/p>\n<pre><code><Subscription\n  subscription={gql`subscription { parent { child } }`}\n\/>\n  {\n    ({data, error, loading}) => {\n      if (error) return <Error error={error} \/>;\n      if (loading) return <Loading \/>;\n      return <RenderData data={data} \/>;\n    }\n  }\n<\/Subscription>\n<\/code><\/pre>\n<p>Let us use one such <code>Subscription<\/code> component to subscribe to our view and then transform the subscription data to the structure that ChartJS expects. The transforming logic looks like this:<\/p>\n<div>\n<pre><code>let chartJSData = {\n  labels: [],\n  datasets: [{\n    label: \"Max temperature every five seconds\",\n    data: [],\n    pointBackgroundColor: [],\n    borderColor: 'brown',\n    fill: false\n  }]\n};\ndata.last_20_min_temp.forEach((item) => {\n  const humanReadableTime = moment(item.five_sec_interval).format('LTS');\n  chartJSData.labels.push(humanReadableTime);\n  chartJSData.datasets[0].data.push(item.max_temp);\n  chartJSData.datasets[0].pointBackgroundColor.push('brown');\n})\n<\/code><\/pre>\n<\/div>\n<p><strong>Note<\/strong>: <em>You can also use the open-source library <a href=\"https:\/\/github.com\/hasura\/graphql-engine\/tree\/master\/community\/tools\/graphql2chartjs\">graphq2chartjs<\/a> for transforming the data from GraphQL response to a form that ChartJS expects.<\/em><\/p>\n<p>After using this inside the Subscription component, our <code>App.js<\/code> looks like:<\/p>\n<div>\n<pre><code>import React, { Component } from 'react';\nimport { Line } from 'react-chartjs-2';\nimport { Subscription } from 'react-apollo';\nimport gql from 'graphql-tag';\nimport moment from 'moment';\n\nconst TWENTY_MIN_TEMP_SUBSCRIPTION= gql'\n  subscription {\n    last_20_min_temp(\n      order_by: {\n        five_sec_interval: asc\n      }\n      where: {\n        location: {\n          _eq: \"London\"\n        }\n      }\n    ) {\n      five_sec_interval\n      location\n      max_temp\n    }\n  }\n'\n\nclass App extends Component {\n  render() {\n    return (\n      <div\n        style={{display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '20px'}}\n      >\n        <Subscription subscription={TWENTY_MIN_TEMP_SUBSCRIPTION}>\n          {\n            ({data, error, loading}) => {\n              if (error) {\n                console.error(error);\n                return \"Error\";\n              }\n              if (loading) {\n                return \"Loading\";\n              }\n              let chartJSData = {\n                labels: [],\n                datasets: [{\n                  label: \"Max temperature every five seconds\",\n                  data: [],\n                  pointBackgroundColor: [],\n                  borderColor: 'brown',\n                  fill: false\n                }]\n              };\n              data.last_20_min_temp.forEach((item) => {\n                const humanReadableTime = moment(item.five_sec_interval).format('LTS');\n                chartJSData.labels.push(humanReadableTime);\n                chartJSData.datasets[0].data.push(item.max_temp);\n                chartJSData.datasets[0].pointBackgroundColor.push('brown');\n              })\n              return (\n                <Line\n                  data={chartJSData}\n                  options={{\n                    animation: {duration: 0},\n                    scales: { yAxes: [{ticks: { min: 5, max: 20 }}]}\n                  }}\n                \/>\n              );\n            }\n          }\n        <\/Subscription>\n      <\/div>\n    );\n  }\n}\n\nexport default App;\n<\/code><\/pre>\n<\/div>\n<p>You will have a fully working real-time chart ready at <code>http:\/\/localhost:3000<\/code> . However, it would be empty, so let\u2019s populate some sample data so we can actually see some magic happen.<\/p>\n<p><strong>Note<\/strong>: <em>I have added some more options to the Line chart because I don\u2019t like those fancy animations in ChartJS. A time series looks sweet when it\u2019s simple, however, you can remove the options prop if you like.<\/em><\/p>\n<h4>Inserting Sample Data<\/h4>\n<p>Lets write a script that populates our database with dummy data. Create a separate directory (outside this app) and create a file called <code>script.js<\/code> with the following content,<\/p>\n<div>\n<pre><code>const fetch = require('node-fetch');\nsetInterval(\n  () => {\n    const randomTemp = (Math.random() * 5) + 10;\n    fetch(\n      `http:\/\/localhost:8080\/v1alpha1\/graphql`,\n      {\n        method: 'POST',\n        body: JSON.stringify({\n          query: `\n            mutation ($temp: numeric) {\n              insert_temperature (\n                objects: [{\n                  temperature: $temp\n                  location: \"London\"\n                }]\n              ) {\n                returning {\n                  recorded_at\n                  temperature\n                }\n              }\n            }\n          `,\n          variables: {\n            temp: randomTemp\n          }\n        })\n      }\n    ).then((resp) => resp.json().then((respObj) => console.log(JSON.stringify(respObj, null, 2))));\n  },\n  2000\n);\n<\/code><\/pre>\n<\/div>\n<p>Now run these two commands:<\/p>\n<pre><code>npm install --save node-fetch\nnode script.js\n<\/code><\/pre>\n<p>You can go back to <code>http:\/\/localhost:3000<\/code> and see the chart updating.<\/p>\n<h3>Finishing Up<\/h3>\n<p>You can build most of the real-time charts using the ideas that we discussed above. The algorithm is:<\/p>\n<ol>\n<li>Deploy GraphQL Engine with Postgres;<\/li>\n<li>Create tables where you wish to store data;<\/li>\n<li>Subscribe to those tables from your React app;<\/li>\n<li>Render the chart.<\/li>\n<\/ol>\n<p>You can find the source code <a href=\"https:\/\/github.com\/wawhal\/graphql-live-time-series\">here<\/a>.<\/p>\n<div>\n  <img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/logo-red-19.png?w=900\" alt=\"Smashing Editorial\"><span>(dm, ra, il)<\/span>\n<\/div>\n<\/article>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Building Real-Time Charts With GraphQL And Postgres Building Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00 Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users&#8230;<a class=\"moretag\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/\"> Read the full article&#8230;<\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[371],"tags":[],"class_list":["post-62537","post","type-post","status-publish","format-standard","hentry","category-user-experience"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Guest Contribution\"\/>\n\t<meta name=\"keywords\" content=\"user experience\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies\" \/>\n\t\t<meta property=\"og:description\" content=\"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-03-28T11:19:50+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-03-28T11:19:50+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#article\",\"name\":\"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies\",\"headline\":\"Building Real-Time Charts With GraphQL And Postgres\",\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/realtime-charts-graphql-postgres-demo.gif?fit=%2C&ssl=1\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#articleImage\"},\"datePublished\":\"2019-03-28T04:19:50-07:00\",\"dateModified\":\"2019-03-28T04:19:50-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#webpage\"},\"articleSection\":\"User Experience\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"position\":2,\"name\":\"User Experience\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#listItem\",\"name\":\"Building Real-Time Charts With GraphQL And Postgres\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#listItem\",\"position\":3,\"name\":\"Building Real-Time Charts With GraphQL And Postgres\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/\",\"name\":\"Guest Contribution\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Guest Contribution\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#webpage\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/\",\"name\":\"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies\",\"description\":\"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/03\\\/building-real-time-charts-with-graphql-and-postgres\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"datePublished\":\"2019-03-28T04:19:50-07:00\",\"dateModified\":\"2019-03-28T04:19:50-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies","description":"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients","canonical_url":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/","robots":"max-image-preview:large","keywords":"user experience","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#article","name":"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies","headline":"Building Real-Time Charts With GraphQL And Postgres","author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/03\/realtime-charts-graphql-postgres-demo.gif?fit=%2C&ssl=1","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#articleImage"},"datePublished":"2019-03-28T04:19:50-07:00","dateModified":"2019-03-28T04:19:50-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#webpage"},"isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#webpage"},"articleSection":"User Experience"},{"@type":"BreadcrumbList","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.taterboy.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","position":2,"name":"User Experience","item":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#listItem","name":"Building Real-Time Charts With GraphQL And Postgres"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#listItem","position":3,"name":"Building Real-Time Charts With GraphQL And Postgres","previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}}]},{"@type":"Organization","@id":"https:\/\/www.taterboy.com\/blog\/#organization","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","url":"https:\/\/www.taterboy.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author","url":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/","name":"Guest Contribution","image":{"@type":"ImageObject","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g","width":96,"height":96,"caption":"Guest Contribution"}},{"@type":"WebPage","@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#webpage","url":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/","name":"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies","description":"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/#breadcrumblist"},"author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"creator":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"datePublished":"2019-03-28T04:19:50-07:00","dateModified":"2019-03-28T04:19:50-07:00"},{"@type":"WebSite","@id":"https:\/\/www.taterboy.com\/blog\/#website","url":"https:\/\/www.taterboy.com\/blog\/","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","og:type":"article","og:title":"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies","og:description":"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients","og:url":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/","article:published_time":"2019-03-28T11:19:50+00:00","article:modified_time":"2019-03-28T11:19:50+00:00","twitter:card":"summary","twitter:title":"Building Real-Time Charts With GraphQL And Postgres | Design for Immersive Technologies","twitter:description":"Building Real-Time Charts With GraphQL And PostgresBuilding Real-Time Charts With GraphQL And Postgres Rishichandra Wawhal 2019-03-27T13:00:08+01:002019-03-28T11:06:14+00:00Charts form an integral part of any industry that deals with data. Charts are useful in the voting and polling industry, and they\u2019re also great at helping us better understand the different behaviors and characteristics of the users and clients"},"aioseo_meta_data":{"post_id":"62537","title":null,"description":null,"keywords":null,"keyphrases":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_custom_image_width":null,"og_custom_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"created":"2021-02-07 21:24:39","updated":"2026-09-01 07:32:00","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"twitter_image_url":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/\" title=\"User Experience\">User Experience<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tBuilding Real-Time Charts With GraphQL And Postgres\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.taterboy.com\/blog"},{"label":"User Experience","link":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/"},{"label":"Building Real-Time Charts With GraphQL And Postgres","link":"https:\/\/www.taterboy.com\/blog\/2019\/03\/building-real-time-charts-with-graphql-and-postgres\/"}],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8wzr5-ggF","jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/62537","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/comments?post=62537"}],"version-history":[{"count":0,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/62537\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media?parent=62537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/categories?post=62537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/tags?post=62537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}