| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| --> |
| |
| # Node.js Native API |
| |
| The Node.js native API supports interacting with the IoTDB table model through `TableSessionPool`, enabling data insertion, queries, non-query SQL, and connection management under the table model. Building on connection pool capabilities, `TableSessionPool` adds database context management, making it suitable for accessing relational table data in Node.js applications. |
| |
| This document focuses on the usage of `TableSessionPool`, covering environment preparation, core steps, and common interfaces. |
| |
| ## 1. Environment Preparation |
| |
| ### 1.1 Prerequisites |
| |
| * Node.js >= 14.0.0 |
| * npm >= 6.0.0 |
| * IoTDB >= 2.0.11 |
| |
| ### 1.2 Installation |
| |
| * **Option 1: Install directly via npm (recommended)** |
| |
| Run the following command in your Node.js project: |
| |
| ```bash |
| npm install @iotdb/client |
| ``` |
| |
| * **Option 2: Build from source** |
| |
| To use the development version from the repository, clone the source code and install dependencies: |
| |
| ```bash |
| git clone https://github.com/apache/iotdb-client-nodejs.git |
| cd iotdb-client-nodejs |
| git checkout develop |
| npm ci |
| ``` |
| |
| On Linux, macOS, or WSL, run: |
| |
| ```bash |
| npm run build |
| ``` |
| |
| On Windows PowerShell, run: |
| |
| ```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 -Force |
| ``` |
| |
| After the build is complete, you can install the client locally in your business project via the absolute path of the client source directory: |
| |
| ```bash |
| npm install /absolute/path/to/iotdb-client-nodejs |
| ``` |
| |
| If you use TypeScript, no additional type declarations are required. The client comes 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 operating the IoTDB table model with the Node.js native API are as follows: |
| |
| 1. Create a connection pool instance: initialize a `TableSessionPool` object with connection parameters, database, and pool size. |
| 2. Execute database operations: perform table creation, data insertion, or queries directly through the connection pool. |
| 3. Close the connection pool: call `tablePool.close()` when the program ends to release all connections. |
| |
| The following sections describe the core development workflow and do not demonstrate all parameters and interfaces. For the complete capabilities, refer to the [`@iotdb/client` source code](https://github.com/apache/iotdb-client-nodejs/tree/develop/src) and [examples](https://github.com/apache/iotdb-client-nodejs/tree/develop/examples). |
| |
| ### 2.1 Creating a Connection Pool Instance |
| |
| #### 2.1.1 Single-Node Connection |
| |
| ```typescript |
| import { TableSessionPool } from '@iotdb/client'; |
| |
| const tablePool = new TableSessionPool('localhost', 6667, { |
| username: 'root', |
| password: 'root', |
| database: 'test', |
| maxPoolSize: 10, |
| minPoolSize: 2, |
| }); |
| |
| await tablePool.init(); |
| ``` |
| |
| Here `database` sets the default database for the table model. Once configured, the connection pool uses this database context for queries and writes. |
| |
| #### 2.1.2 Multi-Node Connection |
| |
| In a cluster environment, it is recommended to configure multiple nodes with `nodeUrls`. The connection pool distributes connections across nodes in a round-robin manner and tries other available nodes when a connection fails. |
| |
| ```typescript |
| import { TableSessionPool } from '@iotdb/client'; |
| |
| const tablePool = new TableSessionPool({ |
| nodeUrls: [ |
| '192.168.1.100:6667', |
| '192.168.1.101:6667', |
| '192.168.1.102:6667', |
| ], |
| username: 'root', |
| password: 'root', |
| database: 'test', |
| maxPoolSize: 10, |
| minPoolSize: 2, |
| }); |
| |
| await tablePool.init(); |
| ``` |
| |
| Connection pool parameters can be adjusted according to your workload: `minPoolSize` is recommended to be set to the average concurrent load, while `maxPoolSize` should 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 waiting 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. |
| |
| ```typescript |
| import { TableSessionPool } from '@iotdb/client'; |
| import * as fs from 'fs'; |
| |
| const tablePool = new TableSessionPool({ |
| host: 'localhost', |
| port: 6667, |
| username: 'root', |
| password: 'root', |
| database: 'test', |
| 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 tablePool.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 target route and prefers a more suitable node for subsequent writes. |
| |
| ```typescript |
| import { TableSessionPool } from '@iotdb/client'; |
| |
| const tablePool = new TableSessionPool({ |
| nodeUrls: [ |
| '192.168.1.100:6667', |
| '192.168.1.101:6667', |
| '192.168.1.102:6667', |
| ], |
| username: 'root', |
| password: 'root', |
| database: 'test', |
| maxPoolSize: 10, |
| enableRedirection: true, |
| redirectCacheTTL: 300000, |
| }); |
| |
| await tablePool.init(); |
| ``` |
| |
| With redirection enabled, cross-node forwarding is reduced, improving write throughput and lowering network latency. |
| |
| ### 2.2 Database Operations |
| |
| #### 2.2.1 Creating a Database and a Table |
| |
| ```typescript |
| await tablePool.executeNonQueryStatement('CREATE DATABASE IF NOT EXISTS test'); |
| |
| await tablePool.executeNonQueryStatement('USE test'); |
| |
| await tablePool.executeNonQueryStatement(` |
| CREATE TABLE IF NOT EXISTS device_metrics ( |
| time TIMESTAMP TIME, |
| device_id STRING TAG, |
| region STRING ATTRIBUTE, |
| temperature FLOAT FIELD, |
| humidity FLOAT FIELD |
| ) |
| `); |
| ``` |
| |
| #### 2.2.2 Inserting Tablet Data |
| |
| When writing in the table model, you need to specify the table name, column names, data types, timestamps, and values. The following example organizes `values` by column, where each array corresponds to a non-time column. |
| |
| ```typescript |
| import { ColumnCategory, TSDataType } from '@iotdb/client'; |
| |
| await tablePool.insertTablet({ |
| tableName: 'device_metrics', |
| columnNames: ['device_id', 'region', 'temperature', 'humidity'], |
| columnTypes: [ |
| TSDataType.STRING, |
| TSDataType.STRING, |
| TSDataType.FLOAT, |
| TSDataType.FLOAT, |
| ], |
| columnCategories: [ |
| ColumnCategory.TAG, |
| ColumnCategory.ATTRIBUTE, |
| ColumnCategory.FIELD, |
| ColumnCategory.FIELD, |
| ], |
| timestamps: [Date.now(), Date.now() + 1000], |
| values: [ |
| ['device_1', 'beijing', 25.5, 60.0], |
| ['device_1', 'beijing', 26.0, 61.5], |
| ], |
| }); |
| ``` |
| |
| If your project does not use the enums directly, `columnTypes` can also use data type codes. |
| |
| For data insertion, it is recommended to use `insertTablet` for batch writes to reduce network round trips. A common batch size to start with is 100 to 1000 rows, then adjust based on data volume, network, and server resources. |
| |
| #### 2.2.3 Querying Data |
| |
| Query results are returned through `SessionDataSet`. Call `close()` after use to release server-side query resources. |
| |
| ```typescript |
| const dataSet = await tablePool.executeQueryStatement(` |
| SELECT time, device_id, region, temperature, humidity |
| FROM device_metrics |
| WHERE device_id = 'device_1' |
| `); |
| |
| while (await dataSet.hasNext()) { |
| const row = dataSet.next(); |
| console.log(row.getFields()); |
| } |
| |
| await dataSet.close(); |
| ``` |
| |
| For small result sets, you can also use `toArray()` to load all results into memory: |
| |
| ```typescript |
| const dataSet = await tablePool.executeQueryStatement('SHOW TABLES'); |
| const rows = await dataSet.toArray(); |
| console.log(rows); |
| await dataSet.close(); |
| ``` |
| |
| ### 2.3 Closing the Connection Pool |
| |
| ```typescript |
| await tablePool.close(); |
| ``` |
| |
| It is recommended to close the connection pool uniformly when the application exits, a scheduled task ends, or the service is destroyed, to avoid connection leaks. |
| |
| ## 3. Common Interfaces |
| |
| ### 3.1 TableSessionPool |
| |
| #### 3.1.1 Description |
| |
| `TableSessionPool` is the recommended connection pool interface for the table model. It supports automatic session management and database context management. When a query, insert, or non-query method is called, the pool automatically acquires an available session and recycles the connection after execution. |
| |
| #### 3.1.2 Constructors |
| |
| | Constructor | Description | |
| | --- | --- | |
| | `new TableSessionPool(host, port, config)` | Traditional constructor, suitable for single-node connections | |
| | `new TableSessionPool(config)` | Constructed with a configuration object, suitable for `nodeUrls` multi-node configurations | |
| | `new TableSessionPool(new PoolConfigBuilder().build())` | Constructed with the builder pattern, recommended when there are many parameters | |
| |
| #### 3.1.3 Methods |
| |
| | Method | Description | |
| | --- | --- | |
| | `init()` | Initializes the connection pool | |
| | `close()` | Closes the connection pool and releases all connections | |
| | `executeQueryStatement(sql, timeoutMs?)` | Executes a query SQL, with an optional query timeout | |
| | `executeNonQueryStatement(sql)` | Executes a non-query SQL, such as DDL or DML | |
| | `insertTablet(tablet)` | Inserts table model Tablet data | |
| | `getPoolSize()` | Gets the current pool size | |
| | `getAvailableSize()` | Gets the current number of available connections | |
| | `getInUseSize()` | Gets the current number of connections in use | |
| |
| #### 3.1.4 Configuration Options |
| |
| | Option | Description | |
| | --- | --- | |
| | `host` | Host address | |
| | `port` | Port | |
| | `nodeUrls` | Multiple node addresses, in the format `host:port` | |
| | `username` | User name | |
| | `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 options | |
| | `enableRedirection` | Whether to enable write redirection | |
| | `redirectCacheTTL` | Redirection cache expiration time in milliseconds | |
| |
| ### 3.2 Tablet Parameters |
| |
| The common parameters of `insertTablet` in the table model are as follows: |
| |
| | Parameter | Description | |
| | --- | --- | |
| | `tableName` | Target table name | |
| | `columnNames` | List of non-time column names | |
| | `dataTypes` | List of data types for non-time columns | |
| | `columnCategories` | List of categories for non-time columns | |
| | `timestamps` | List of timestamps | |
| | `values` | List of column values, organized by column | |
| |
| The orders of `columnNames`, `columnTypes`, `columnCategories`, and `values` must be consistent. |
| |
| ## 4. Data Types |
| |
| When inserting Tablet data, you need to specify the corresponding data type for each column. 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 the `INT64` type, it is recommended to use `bigint` in JavaScript to avoid precision loss when values exceed the safe integer range of `number`. |
| |
| ## 5. FAQ |
| |
| 1. Default database does not exist: If the configured `database` does not exist when the connection pool is initialized, first execute `CREATE DATABASE`, then explicitly execute `USE database_name` before creating tables, querying, or writing. Alternatively, create the database before initializing `TableSessionPool`. |
| |
| 2. Column mismatch: If a column count or type mismatch occurs during insertion, check whether the orders and lengths of `columnNames`, `columnTypes`, `columnCategories`, and `values` are consistent, and confirm that `values` are organized by row and the table schema matches the written data. |
| |
| 3. Query results consume too much memory: For large result sets, it is recommended to read in batches with `hasNext()` and `next()` and reduce `fetchSize`. Use `toArray()` only for small result sets. |
| |
| 4. Connection acquisition timeout: If waiting for an available connection times out, the pool is usually exhausted. Increase `waitTimeout` or `maxPoolSize` as appropriate, and check whether there are query result sets that have not been closed for a long time. |