Asynchronous CRUD Pie Chart Using Node/Mongo REST API
Table Of Contents:
We are going to go over the basics and best practices of getting data from an endpoint. The end game is to get data and update chart data through this endpoint through user interactions.
In this case, we have created a node/express server which hits a mongoDB instance hosted by mLab.
The MongoDB instance zingchart-crud-chart-blog-post
has one collection called machine-data
. The collection structure is as follows:
{
"_id": {...},
"type": "v1" // "v1" || "v2"
"temp": 195,
}
This is for showing how to load data. zingchart-crud-chart-blog-post
has a second collection called rest-example
, which is used for the final CRUD chart example. The structure is as follows:
{
"_id": "8840252070117893", // sessionId for user
"plots": [ // chart plots or as ZingChart likes to call them, series objects
{
"text": "Newspaper",
"value": 15
},
{
"text": "Digital",
"value": 55
},
{
"text": "Billboard",
"value": 25
},
{
"text": "Success??",
"value": 35
},
{
"text": "Please Work",
"value": 35
}
]
}
AJAX Chart
For the first chart, we are going to make an AJAX GET
request using the standardized XMLHttpRequest()
provided by Web API.
- You should use whatever AJAX wrapper you are comfortable with or is already built into the framework you are using.
We will request some data and render a chart based on the returned array of values.
First set up the basic request:
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "https://zingchart-rest-api.gomix.me/api/data");
oReq.send();
Let's take a peek into our server code for the requested URL https://zingchart-rest-api.gomix.me/api/data
app.get("/api/data", (req, res) => {
const entries = dbConnection.collection('machine-data');
entries.find({}).toArray( (err, docs) => {
let chartValues = docs.map(function(curVal, index, array) {
return curVal.temp;
});
res.send(chartValues);
});
});
Second, render the chart based on the returned array.
/*
* callback for GET request is when we will render the chart
*/
function reqListener () {
myConfig.series[0].values = JSON.parse(this.responseText);
zingchart.render({
id: 'myChart',
data: myConfig,
height: '100%',
width: '100%'
});
}
Parsing Multiple Plots Into ZingChart
You can get multiple plots into the chart several ways. Depending on the data size, user base, project requirements, and skillset, you may either want to do the heavy lifting on the server, client, or even a bit of both.
Server Side Parsing
You can do all the heavy lifting on the server and return the chart syntax needed. This may be a good decision if your user base has slower machines.
Doing server side parsing, you can guarantee the same parse speed because it's your hardware, but the bottleneck is still the network.
This will make a request to the route "/api/data/getAllPlots/seriesObject"
which can be viewed here.
Client Side Parsing
You can return the database JSON and do some client side parsing on your own. I just encountered a solution that actually reduced the packet size by 1/3 from sending over the raw JSON instead of parsing it into the ZingChart syntax.
This was because there were several plots all using the same timestamp for each point. It looked something like [timestamp,value]
. Each plot had a different value, but the same timestamp. Why send a packet over the network with 9 duplicate arrays of timestamps?
In this example, there is virtually no difference in the code used to parse the data from the above server example. This is because both technologies are JavaScript.
The decision of where to do the parsing depends on your server side technologies and comfortability with that language, separation of concerns, and a long list of design decisions that I'm not going to go into.
Let's make make a request to "/api/data/getAllPlots/JSON"
which can be viewed here.
Server + Client Side Parsing
You can do a bit of both server and client side rendering by making several calls and asynchronously loading the plots. This is a great approach because you can see several benefits.
The packet sizes are smaller. Each request will be a small subset of the overall data you are showing.
You will see a benefit with big data using this approach. Think of time to first byte. This is the same approach. The time for users to see something on the chart they can interact with comes first. Then, as the other HTTP requests come in, the data will load itself in for the user to see.
You may say, let's cache the data/request, it's fine. The idea of caching everything on a site is great, but that really is a benefit to your hardcore users. Users who actually interact and visit a large portion of your site. The reality is, users are skimming through and may only interact with a small portion of your site.
So why penalize them with long first load times? This is where web components are starting to come in, but I'm going to leave this rant short. The concept is simple- only load the necessary content for interaction, this includes CSS, HTML, and of course charts!
Users who only view the chart once (or not at all) are not penalized. The reality is, charts may only be a small portion of your app or dashboard. Some users may or may not be dependent on them.
Don't block the page by rendering a bunch of JS that your user might not care about. Do the research to find out if they care... obviously.
- I used
setTimeout
in between requests so you visually can see the intervals the requests are fired off in. If I didn't do this you have about 10 ms in between requests.
If you're a hawk or mountain lion, you might have the reaction speed to see this. But I doubt that. Let's be honest, you're average like the rest of us.
I'm not here to tell you which method is better or worse than the other. If one of the methods above fits your framework, use case, or skillset better, choose that way. Whatever decision you make, be pragmatic about it.
Most important, understand your users. Do the research to find this out. Set up tracking with Piwik, Hotjar, Fullstory, etc.
Don't just throw up Google analytics and call it a day. That's not giving you the information you need. That's just giving management something nice to look at.
Full CRUD and REST (ish) Chart
The final chart is here! You can see how to hook your DB up to an interactive chart. We have covered the simple GET
request to retrieve data from the database.