
Introduction
InfluxDB is a high-performance time-series database written in the Go programming language. The open-source database application supports several hundred thousand writes per second. InfluxDB optimization for speed makes it the most suitable database server for storing and monitoring time-stamped metrics. The metrics are useful in IoT, financial, transportation, and telecommunication industries.
Node.js is a cross-platform run-time engine that executes Javascript code. Node.js competes with other modern backend programming languages like PHP, Go, and Python. The Node.js non-blocking model makes it a suitable choice for highly-available applications such as chat applications, real-time collaborating tools, streaming applications, and more.
This guide shows you how to code a Node.js application that interacts with an InfluxDB database server On Ubuntu 20.04. The application writes data points to InfluxDB and queries the database to present the information in an HTML table.
Prerequisites
To follow along with this guide:
Create a non-root
sudouser and install the following packages:
1. Set Up a Sample Database
In this guide, your sample application stores data permanently on an InfluxDB server. The data may come from IoT devices such as smartwatches, energy meters, bank applications, and more in a production environment. This guide uses sample data from solar customers. The energy consumed by the customers in kilowatt-hours, otherwise known as a KWh, is live-streamed to the application via the HTTP protocol. Then, the application stores the data in the InfluxDB server for further processing.
SSH to your server and execute the following steps to create and initialize a sample InfluxDB database:
Log in to the InfluxDB server. Replace
adminandEXAMPLE_PASSWORDwith the correct InfluxDB administrator credentials.$ influx -username 'admin' -password 'EXAMPLE_PASSWORD'Output.
>Create a sample
solar_customersdatabase.> CREATE DATABASE solar_customersOutput.
>Switch to the new
solar_customersdatabase.> USE solar_customersOutput.
Using database solar_customersInsert sample data points into the
solar_customersdatabase. Specifypower_usageas the metric name. In the InfluxDB model, a data point (For instance,power_usage,customer_id=1 KWh=800) is like a record, and a metric (For example,power_usage) is like a table in SQL-based databases.> INSERT power_usage,customer_id=1 KWh=800 > INSERT power_usage,customer_id=2 KWh=1750 > INSERT power_usage,customer_id=3 KWh=2560 > INSERT power_usage,customer_id=4 KWh=652 > INSERT power_usage,customer_id=5 KWh=920Output.
... >Query the
power_usagemetric to ensure the data is in place.> SELECT "customer_id", "KWh" FROM "power_usage"Output.
time customer_id KWh ---- ----------- --- 1662015648115956829 1 800 1662015655675425278 2 1750 1662015662345951963 3 2560 1662015669315582055 4 652 1662015675915505403 5 920Log out from the InfluxDB server.
> quit
The sample database is now ready to accept new data points. Proceed to the next step, creating a Node.js module for accessing the InfluxDB database.
2. Create a Database Gateway Class
When creating a data-driven application with Node.js, it is conventional to have a separate class that provides database functions to the rest of the Node.js modules. A separate database gateway class allows you to define your database credentials in a single file making troubleshooting straightforward in case the application fails to connect to the database. Follow the steps below to create the class:
Create a
projectdirectory for the Node.js application.$ mkdir projectSwitch to the new
projectdirectory.$ cd projectOpen a new
database_gateway.jsfile in a text editor.$ nano influxdb_gateway.jsEnter the following information into the
influxdb_gateway.jsfile. ReplaceEXAMPLE_PASSWORDwith the correct password for the InfluxDBadminaccount.class influxdb_gateway { dbConn() { const influxDb = require('influxdb-nodejs'); const dbHost = '127.0.0.1'; const dbPort = '8086'; const dbUser = 'admin'; const dbPass = 'EXAMPLE_PASSWORD'; const dbName = 'solar_customers'; const conString = 'http://' dbUser ':' dbPass '@' dbHost ':' dbPort '/' dbName; const influxDbClient = new influxDb(conString); return influxDbClient; } } module.exports = influxdb_gateway;Save and close the
database_gateway.jsfile.
The influxdb_gateway.js file explained:
The
influxdb_gateway.jscontains a singleinfluxdb_gatewayclass. The class then houses adbConn()method.class influxdb_gateway { dbConn() { ... } } ...The
dbConn()method loads theinfluxdb-nodejsmodule. This module provides InfluxDB functionalities to the Node.js application. Then, thedbConn()method connects to the InfluxDB server and returns the connection using theconst influxDbClient = new influxDb(conString);andreturn influxDbClient;statements.The
module.exports = influxdb_gateway;at the end of the file allows you to import and use theinfluxdb_gatewaymodule in other Node.js source code files using the following declarations.const influxdb_gateway = require('./influxdb_gateway'); const dg = new influxdb_gateway(); const dbConn = dg.dbConn();
After coding the database gateway class, the next step involves creating a module that manages the InfluxDB power_usage metric.
3. Create the Database Metric class
This application measures a single power_usage metric for demonstration purposes. Complex applications may contain dozens or hundreds of metrics. Because each metric is different, you should code its functionalities in a separate file. Follow the steps below to create a power_usage metric class:
Open a new
power_usage.jsfile in a text editor.$ nano power_usage.jsEnter the following information into the
power_usage.jsfile.class power_usage { constructor(dbConn) { this.dbConn = dbConn; this.measurement = 'power_usage'; } readPoints(callBack) { const reader = this.dbConn.query(this.measurement); reader.then(function (data) { const dataPoints = data.results[0].series[0].values; const dataColumns = data.results[0].series[0].columns; callBack(dataPoints, dataColumns) }).catch( console.error ); } writePoint(pointData, callBack) { this.dbConn.write(this.measurement).tag({ customer_id: pointData["customer_id"] }).field({ KWh: pointData["KWh"] }).then( callBack("Success.") ).catch( console.error ); } } module.exports = power_usage;Save and close the
power_usage.jsfile.
The power_usage.js file explained:
The
power_usage.jsfile contains onepower_usageclass and three methods.class power_usage { constructor(dbConn) { ... } readPoints(callBack) { ... } writePoint(pointData, callBack) { ... } }The methods in the
power_usageclass perform the following functions:constructor(dbConn): This method initializes thepower_usageclass. The constructor method accepts adbConnargument containing a connection to the InfluxDB server. Thethis.measurement = 'power_usage';statement sets the name of the measurement. When initializing thepower_usageclass, you must pass an InfluxDB server connection through the constructor function per the following illustration.const power_usage = require('./power_usage'); const pu = new power_usage(dbConn);readPoints(callBack): This method runs thethis.dbConn.query(this.measurement);function that queries and retrieves data points from the InfluxDB server. ThecallBackargument accepts a function that runs when the method completes executing. After thereadPoints(callBack)method runs, it returns the data points and data columns to the calling function using thecallBack(dataPoints, dataColumns)statement.writePoint(pointData, callBack): This method writes a new measurement data point to the InfluxDB server by running thethis.dbConn.write(this.measurement).tag({...}).field({...})function. ThewritePoint(...)function accepts thepointDatain JSON format and thecallBackfunction that runs when the method completes.
The
module.exports = power_usage;declaration at the end of thepower_usageclass avails the module to other source code files. Using the following code block, you may initialize and use thepower_usagemodule.const power_usage = require('./power_usage'); const pu = new power_usage(dbConn); pu.readPoints(callBack); pu.writePoint(dataPoints, callBack);
After coding the power_usage metric class, create the application's entry point in the next step.
4. Create the Application's Entry Point
Every Node.js application must have an entry point. This is the main file that runs when the application starts. The sample application in this guide runs through an index.js file. Create the file by following the steps below.
Open a new
index.jsfile for editing purposes.$ nano index.jsEnter the following information into the
index.jsfile. Replace172.16.0.1with your server's private IP address.const http = require('http'); const influxdb_gateway = require('./influxdb_gateway'); const power_usage = require('./power_usage'); const httpHost = '172.16.0.1'; const httpPort = 8080; const server = http.createServer(httpHandler); server.listen(httpPort, httpHost, () => { console.log(`Server running at http://${httpHost}:${httpPort}/`); }); function httpHandler(req, res) { const dg = new influxdb_gateway(); const dbConn = dg.dbConn(); const pu = new power_usage(dbConn); res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); if (req.method == 'POST') { var httpPayload = ""; req.on('data', function (data) { httpPayload = data; }); req.on('end', function () { pu.writePoint(JSON.parse(httpPayload), writeCallBack); }); } function writeCallBack(response) { res.write(response 'rn'); res.end(); } if (req.method == 'GET') { pu.readPoints(readCallBack); } function readCallBack(dataPoints, dataColumns) { var tableHeaders = ''; for (var columnIndex in dataColumns) { tableHeaders = '<th>' dataColumns[columnIndex] '</th>'; } var rows = ''; for (var rowIndex in dataPoints) { var rowData = '<tr>'; for (var columnIndex in dataPoints[rowIndex]) { rowData = '<td>' dataPoints[rowIndex][columnIndex] '</td>'; } rowData = '</tr>'; rows = rowData; } const tableData = "<table border = '1' align = 'center'><tr>" tableHeaders "</tr>" rows "</table>"; const html = `<!DOCTYPE html> <html> <body align = 'center'> <h1>Power Usage For Customers</h1><hr>` tableData `</body> </html>`; res.write(html); res.end(); } }Save and close the
index.jsfile.
The index.js file explained:
The
...require(...)section loads all the modules the application requires to run. Thehttpmodule offers HTTP functionalities to your application and allows you to run a web server. Theinfluxdb_gatewayandpower_usagestatements load the custom classes you coded earlier.const http = require('http'); const influxdb_gateway = require('./influxdb_gateway'); const power_usage = require('./power_usage'); ...The next four lines initialize a web server that listens for incoming connections under port
8080. Then, thehttp.createServer(httpHandler);statement passeshttpHandleras the handler function for incoming HTTP requests.... const httpHost = '172.16.0.1'; const httpPort = 8080; const server = http.createServer(httpHandler); server.listen(httpPort, httpHost, () => { console.log(`Server running at http://${httpHost}:${httpPort}/`); }); ...The
httpHandler(req, res)function initializes theinfluxdb_gatewayand thepower_usagemodules using the following statements.... const dg = new influxdb_gateway(); const dbConn = dg.dbConn(); const pu = new power_usage(dbConn); ...The next two lines set the correct HTTP headers for the application to allow HTTP clients to treat the data as HTML.
... res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); ...The logical
if (...){...}statements examine the HTTP method to determine the appropriate method to run. ForPOSTrequests (if (req.method == 'POST') {...}), the application runs thepu.writePoint(JSON.parse(httpPayload), writeCallBack);function to write the data points to the InfluxDB database. ForGETrequests (if (req.method == 'GET') {...}), the application runs thepu.readPoints(readCallBack);function to read the data points from the InfluxDB database.The
writeCallBack(...)function executes when the application writes data successfully into the database. ThewriteCallBack(...)function returns aSuccess.message.... function writeCallBack(response) { res.write(response 'rn'); res.end(); } ...The
readCallBack(dataPoints, dataColumns)function runs when the application retrieves data from the InfluxDB database and displays the data in HTML format. Thefor (var columnIndex in dataColumns){...}loop sets the HTML table headers. Then, thefor (var rowIndex in dataPoints) {...}loop populates the HTML table rows.... function readCallBack(dataPoints, dataColumns) { ... for (var columnIndex in dataColumns) { tableHeaders = '<th>' dataColumns[columnIndex] '</th>'; } var rows = ''; for (var rowIndex in dataPoints) { var rowData = '<tr>'; for (var columnIndex in dataPoints[rowIndex]) { rowData = '<td>' dataPoints[rowIndex][columnIndex] '</td>'; } rowData = '</tr>'; rows = rowData; } ... res.write(html); res.end(); } ...
You now have all the required application's source code files. Test the application in the next step.
5. Test the Application
The final step in this guide involves the following:
Initializing the
projectdirectory.Installing the
influxdb-nodejsmodule using thenpmpackage.Inserting new data points using the Linux
curlcommand.Displaying the InfluxDB data points on an HTML web page.
Follow the steps below to complete the above steps:
Ensure your Node.js
npmpackage is up to date.$ sudo npm install npm -gOutput.
changed 54 packages, and audited 212 packages in 2sInitialize the
projectdirectory.$ npm initRespond to the following prompts. For most prompts, you only need to press the Enter to proceed.
package name: (project) :key_enter: version: (1.0.0):key_enter: description: InfluxDB and Node.js :key_enter: entry point: (index.js) :key_enter: test command: :key_enter: git repository: :key_enter: keywords: influxdb, node.js :key_enter: author: Test author :key_enter: license: (ISC) :key_enter: About to write to ... { ... } Is this OK? (yes) yes :key_enter:Install the
influxdb-nodejsmodule.$ npm install influxdb-nodejsOutput.
added 41 packages, and audited 42 packages in 2sRun the project.
$ node index.jsThe application starts a web server that listens for incoming HTTP connections on port
8080. The previous command has a blocking function. Don't run more commands on the active terminal window.Server running at http://172.16.0.1:8080/Establish another
SSHconnection in a new terminal window and run the following commands.$ curl -X POST http://172.16.0.1:8080/ -H 'Content-Type: application/json' -d '{"customer_id": 6, "KWh": 2687}' $ curl -X POST http://172.16.0.1:8080/ -H 'Content-Type: application/json' -d '{"customer_id": 7, "KWh": 1265}' $ curl -X POST http://172.16.0.1:8080/ -H 'Content-Type: application/json' -d '{"customer_id": 8, "KWh": 4268}' $ curl -X POST http://172.16.0.1:8080/ -H 'Content-Type: application/json' -d '{"customer_id": 9, "KWh": 1398}' $ curl -X POST http://172.16.0.1:8080/ -H 'Content-Type: application/json' -d '{"customer_id": 10, "KWh": 7625}'Output.
... Success.Open a web browser and visit the following URL. Replace
172.16.0.1with your server's public IP addressThe following HTML table lists the InfluxDB data points.

Conclusion
This guide shows you how to implement the InfluxDB server with Node.js on Ubuntu 20.04 server. The sample application only uses a few data points for demonstration purposes. However, InfluxDB has rich grouping and mathematical functions that you can use to summarize the data when designing more detailed applications.
Follow the link below to read how to use the InfluxDB server with Golang: