Node.js Native API
Node.js Native API
The Node.js native API supports interacting with the IoTDB tree model through Session and SessionPool, enabling data writing, querying, non-query SQL execution, and connection management. Since Session is not thread-safe, SessionPool is recommended for production environments. Under high-concurrency scenarios, SessionPool centrally manages connection resources and supports multi-node load balancing, failover, and write redirection.
This document focuses on the usage of SessionPool, covering environment preparation, core operation steps, and common interfaces.
1. Environment Preparation
1.1 Prerequisites
Node.js >= 14.0.0
npm >= 6.0.0
IoTDB >= 2.0.11.1
1.2 Installation
- Option 1: Install via npm (Recommended)
Run the following in your Node.js project:
npm install @iotdb/client- Option 2: Build from source
To use the development version from the repository, clone the source code and install dependencies:
git clone https://github.com/apache/iotdb-client-nodejs.git
cd iotdb-client-nodejs
git checkout develop
npm ciOn Linux, macOS, or WSL:
npm run buildOn Windows PowerShell:
npm run build:esbuild
npm run build:types
New-Item -ItemType Directory -Force -Path dist\thrift\generated
Copy-Item src\thrift\generated\*.js,src\thrift\generated\*.d.ts -Destination dist\thrift\generated -ForceAfter the build completes, you can install it locally in your business project via the absolute path of the client source directory:
npm install /absolute/path/to/iotdb-client-nodejsIf you use TypeScript, no additional type declarations are required; the client ships with complete TypeScript type definitions built in.
Note: Do not use a higher-version client to connect to a lower-version server.
2. Core Steps
The three core steps of using the Node.js native API to operate the IoTDB tree model are as follows:
Create a connection pool instance: initialize a
SessionPoolobject and configure connection parameters and pool size.Execute database operations: directly perform data writes, queries, or non-query SQL through the connection pool.
Close the connection pool resources: call
pool.close()when the program exits to release all connections.
The following sections describe the core development flow and do not demonstrate all parameters and interfaces. For the complete capability set, refer to the @iotdb/client source code and examples.
2.1 Create a Connection Pool Instance
2.1.1 Single-Node Connection
import { SessionPool } from '@iotdb/client';
const pool = new SessionPool('localhost', 6667, {
username: 'root',
password: 'TimechoDB@2021',
maxPoolSize: 10,
minPoolSize: 2,
maxIdleTime: 60000,
waitTimeout: 60000,
});
await pool.init();2.1.2 Multi-Node Connection
In a cluster environment, it is recommended to configure multiple nodes via nodeUrls. The connection pool distributes connections across nodes in a round-robin manner and tries other available nodes when a connection fails.
import { SessionPool } from '@iotdb/client';
const pool = new SessionPool({
nodeUrls: [
'192.168.1.100:6667',
'192.168.1.101:6667',
'192.168.1.102:6667',
],
username: 'root',
password: 'TimechoDB@2021',
maxPoolSize: 15,
minPoolSize: 3,
});
await pool.init();You can also use the builder pattern to create the connection pool configuration:
import { SessionPool, PoolConfigBuilder } from '@iotdb/client';
const pool = new SessionPool(
new PoolConfigBuilder()
.nodeUrls([
'192.168.1.100:6667',
'192.168.1.101:6667',
'192.168.1.102:6667',
])
.username('root')
.password('TimechoDB@2021')
.maxPoolSize(15)
.minPoolSize(3)
.build()
);
await pool.init();Connection pool parameters can be adjusted according to business concurrency: minPoolSize is recommended to be set to the average concurrent load, while maxPoolSize is recommended to be set to the peak concurrent load with a 20% to 30% buffer; maxIdleTime is used to clean up long-idle connections, and waitTimeout controls the maximum wait time when the pool is exhausted. In production, it is recommended to monitor getPoolSize(), getAvailableSize(), and getInUseSize(), and adjust the pool size based on peak load.
2.1.3 SSL/TLS Connection
If SSL/TLS is enabled on the IoTDB server, you can enable SSL when creating the connection pool and specify certificate-related parameters.
import { SessionPool } from '@iotdb/client';
import * as fs from 'fs';
const pool = new SessionPool({
host: 'localhost',
port: 6667,
username: 'root',
password: 'TimechoDB@2021',
enableSSL: true,
sslOptions: {
ca: fs.readFileSync('/path/to/ca.crt'),
cert: fs.readFileSync('/path/to/client.crt'),
key: fs.readFileSync('/path/to/client.key'),
rejectUnauthorized: true,
},
});
await pool.init();2.1.4 Write Redirection
In a multi-node IoTDB cluster, the client supports write redirection. When a write operation is sent to a non-target node, the server may return a redirection hint; the client caches the device-to-node mapping and preferentially uses the target node for subsequent writes to the same device.
import { SessionPool } from '@iotdb/client';
const pool = new SessionPool({
nodeUrls: [
'192.168.1.100:6667',
'192.168.1.101:6667',
'192.168.1.102:6667',
],
username: 'root',
password: 'TimechoDB@2021',
maxPoolSize: 10,
enableRedirection: true,
redirectCacheTTL: 300000,
});
await pool.init();With redirection enabled, cross-node forwarding is reduced, improving write throughput and lowering network latency. This capability applies to device-level write scenarios in the tree model.
2.2 Database Operations
2.2.1 Create Database and Time Series
await pool.executeNonQueryStatement('CREATE DATABASE root.test');
await pool.executeNonQueryStatement(
'CREATE TIMESERIES root.test.device1.temperature WITH DATATYPE=FLOAT, ENCODING=RLE'
);
await pool.executeNonQueryStatement(
'CREATE TIMESERIES root.test.device1.humidity WITH DATATYPE=FLOAT, ENCODING=RLE'
);2.2.2 Write Tablet Data
insertTablet supports batch writing of multiple rows by device. values is a two-dimensional array organized by row: each row corresponds to a timestamp, consistent with the order of timestamps; each column corresponds to a measurement, consistent with the order of measurements.
await pool.insertTablet({
deviceId: 'root.test.device1',
measurements: ['temperature', 'humidity'],
dataTypes: [3, 3],
timestamps: [Date.now(), Date.now() + 1000],
values: [
[25.5, 60.0],
[26.0, 61.5],
],
});Here dataTypes can use data type codes, or you can encapsulate them as constants in your project. See Chapter 4 for common type codes.
When writing data, it is recommended to use insertTablet for batch writes to reduce network round trips. A common batch size to start benchmarking is 100 to 1000 rows, then adjust based on data volume, network, and server resources.
2.2.3 Query Data
Query results are returned via SessionDataSet, which supports paginated fetching and is suitable for large result sets. After use, call close() to release server-side query resources.
const dataSet = await pool.executeQueryStatement(
'SELECT temperature, humidity FROM root.test.device1'
);
while (await dataSet.hasNext()) {
const row = dataSet.next();
console.log(row.getTimestamp(), row.getFields());
}
await dataSet.close();For small result sets, you can also use toArray() to load all results into memory:
const dataSet = await pool.executeQueryStatement('SHOW DATABASES');
const rows = await dataSet.toArray();
console.log(rows);
await dataSet.close();2.3 Close the Connection Pool
await pool.close();It is recommended to uniformly close the connection pool when the application exits, scheduled tasks end, or the service is destroyed to avoid connection leaks.
3. Common Interfaces
3.1 SessionPool
3.1.1 Description
SessionPool is the recommended connection pool interface for the tree model, supporting automatic session management. When calling query, write, or non-query methods, the pool automatically acquires an available Session and reclaims the connection after execution.
3.1.2 Construction
| Construction | Description |
|---|---|
new SessionPool(hosts, port, config) | Traditional constructor, suitable for single-node or multi-host same-port configurations |
new SessionPool(config) | Construct with a config object, suitable for nodeUrls multi-node configurations |
new SessionPool(new PoolConfigBuilder().build()) | Construct with the builder pattern, recommended for scenarios with many parameters |
3.1.3 Methods
| Method | Description |
|---|---|
init() | Initialize the connection pool |
close() | Close the connection pool and release all connections |
executeQueryStatement(sql, timeoutMs?) | Execute a query SQL, with optional query timeout |
executeNonQueryStatement(sql) | Execute a non-query SQL, such as DDL or DML |
insertTablet(tablet) | Insert Tablet data |
getSession() | Obtain a Session from the pool, which must be returned manually |
releaseSession(session) | Release a manually acquired Session back to the pool |
getPoolSize() | Get the current pool size |
getAvailableSize() | Get the current number of available connections |
getInUseSize() | Get the current number of connections in use |
3.1.4 Configuration
| Option | Description |
|---|---|
host | Host address |
port | Port |
nodeUrls | Multiple node addresses in host:port format |
username | Username |
password | Password |
database | Default database |
timezone | Time zone |
fetchSize | Batch fetch size for query results |
maxPoolSize | Maximum number of connections |
minPoolSize | Minimum number of connections |
maxIdleTime | Maximum idle time in milliseconds |
waitTimeout | Wait timeout for acquiring a connection in milliseconds |
enableSSL | Whether to enable SSL |
sslOptions | SSL parameters |
enableRedirection | Whether to enable write redirection |
redirectCacheTTL | Redirection cache expiration time in milliseconds |
3.2 Session
3.2.1 Description
Session represents an independent session, suitable for simple scripts or single-threaded scenarios. Session is not thread-safe; use SessionPool for multi-threaded or high-concurrency scenarios.
3.2.2 Methods
| Method | Description |
|---|---|
open() | Open the session |
close() | Close the session |
executeQueryStatement(sql, timeoutMs?) | Execute a query SQL |
executeNonQueryStatement(sql) | Execute a non-query SQL |
insertTablet(tablet) | Insert Tablet data |
isOpen() | Check whether the session is open |
4. Data Types
When inserting Tablet data, you need to specify the corresponding data type for each measurement. The common types supported by the Node.js client are as follows:
| Type Code | Type Name | JavaScript Type | Description |
|---|---|---|---|
0 | BOOLEAN | boolean | Boolean value |
1 | INT32 | number | 32-bit integer |
2 | INT64 | bigint | 64-bit integer |
3 | FLOAT | number | 32-bit floating point |
4 | DOUBLE | number | 64-bit floating point |
5 | TEXT | string | UTF-8 text |
8 | TIMESTAMP | Date | Millisecond-precision timestamp |
9 | DATE | Date | Date type |
10 | BLOB | Buffer | Binary data |
11 | STRING | string | UTF-8 string |
When handling INT64 values, it is recommended to use bigint in JavaScript to avoid precision loss when exceeding the safe integer range of number.
5. FAQ
Connection refused: If
ECONNREFUSEDoccurs, check whether the IoTDB service is started, whether the RPC port is correct, and whether the network and firewall allow access. The default port is usually6667.Connection acquisition timeout: If waiting for an available connection times out, it usually means the pool is exhausted. Increase
waitTimeoutormaxPoolSizeaccordingly, and check whether there are cases where a manually acquiredSessionis not returned viareleaseSession(session).Query results consume too much memory: For large result sets, use
hasNext()andnext()to read in batches and reducefetchSize. Only usetoArray()for small result sets.Unstable write performance: It is recommended to use
insertTabletfor batch writes and adjust the number of rows per batch based on data volume, network, and server resources. In multi-node environments, configurenodeUrlsso the pool distributes load across nodes.