TDengine Node.js 语言连接器入门指南

TDengine Node.js 连接器入门指南

本文面向 TDengine 初学者,目标是让你在 5~10 分钟内完成:安装连接器 → 建立连接 → 建库建表 → 写入 → 查询,并掌握连接器的基本使用方式与常见问题排查。

说明:TDengine 官方 Node.js 连接器为 @tdengine/websocket,通过 taosAdapter 的 WebSocket 接口连接 TDengine。

1. 连接方式

@tdengine/websocket 连接器使用 WebSocket 连接 方式,通过 taosAdapter 的 WebSocket 接口访问 TDengine。这种方式依赖轻量,在并发和 IO 密集场景下表现优异。

连接方式的详细介绍见:

2. 环境准备

在运行示例前,请确认:

  1. TDengine 服务端已启动:确保你的程序能访问到 TDengine 服务。
  2. taosAdapter 已启动@tdengine/websocket 依赖 taosAdapter 的 WebSocket 服务(默认端口 6041)。
  3. Node.js 版本:确保已安装 Node.js 14 及以上版本。

检查 Node.js 版本:

bash 复制代码
node --version

检查 taosAdapter 服务状态:

bash 复制代码
# Linux/macOS
systemctl status taosadapter

# 或直接测试 WebSocket 接口是否可访问
curl -i -N -d "show databases" -u root:taosdata http://localhost:6041/rest/sql

3. 安装连接器

使用 npm 安装:

bash 复制代码
npm install @tdengine/websocket

或使用 yarn:

bash 复制代码
yarn add @tdengine/websocket

4. 第一个程序:建库建表、写入、查询

下面是一个"最小可运行"示例,涵盖了 TDengine 的基本操作。

4.1 完整示例代码

创建文件 quickstart.js

javascript 复制代码
const taos = require("@tdengine/websocket");

async function main() {
    let wsSql = null;
    const host = "127.0.0.1";
    const port = 6041;

    try {
        // 1. 建立连接
        console.log("正在连接 TDengine...");
        let url = `ws://${host}:${port}`;
        let conf = new taos.WSConfig(url);
        conf.setUser("root");
        conf.setPwd("taosdata");

        wsSql = await taos.sqlConnect(conf);
        console.log("✓ 连接成功");

        // 2. 创建数据库
        console.log("\n创建数据库...");
        await wsSql.exec("CREATE DATABASE IF NOT EXISTS demo");
        console.log("✓ 数据库创建成功");

        // 3. 使用数据库
        await wsSql.exec("USE demo");

        // 4. 创建超级表
        console.log("\n创建超级表...");
        await wsSql.exec(
            "CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)"
        );
        console.log("✓ 超级表创建成功");

        // 5. 创建子表并插入数据
        console.log("\n插入数据...");
        await wsSql.exec(
            "INSERT INTO d1001 USING meters TAGS('California.SanFrancisco', 1) VALUES (NOW, 10.3, 219, 0.31)"
        );
        await wsSql.exec(
            "INSERT INTO d1002 USING meters TAGS('California.LosAngeles', 2) VALUES (NOW, 12.6, 218, 0.33)"
        );
        console.log("✓ 数据插入成功");

        // 6. 查询数据
        console.log("\n查询数据...");
        let wsRows = await wsSql.query("SELECT * FROM meters");

        // 获取列信息
        let meta = wsRows.getMeta();
        console.log("\n列信息:");
        meta.forEach((col) => {
            console.log(`  ${col.name} (${col.type})`);
        });

        // 遍历结果集
        console.log("\n查询结果:");
        while (await wsRows.next()) {
            let row = wsRows.getData();
            console.log(row);
        }

        // 关闭结果集
        await wsRows.close();
        console.log("\n✓ 程序执行完成");
    } catch (err) {
        console.error("❌ 错误:", err.message);
        if (err.code) {
            console.error("   错误码:", err.code);
        }
    } finally {
        // 7. 关闭连接
        if (wsSql) {
            await wsSql.destroyed();
            console.log("✓ 连接已关闭");
        }
    }
}

main();

4.2 运行示例

bash 复制代码
node quickstart.js

4.3 预期输出

如果一切正常,你会看到类似以下输出:

复制代码
正在连接 TDengine...
✓ 连接成功

创建数据库...
✓ 数据库创建成功

创建超级表...
✓ 超级表创建成功

插入数据...
✓ 数据插入成功

查询数据...

列信息:
  ts (TIMESTAMP)
  current (FLOAT)
  voltage (INT)
  phase (FLOAT)
  location (BINARY)
  groupId (INT)

查询结果:
[ 2026-01-14T08:30:45.123Z, 10.3, 219, 0.31, 'California.SanFrancisco', 1 ]
[ 2026-01-14T08:30:45.456Z, 12.6, 218, 0.33, 'California.LosAngeles', 2 ]

✓ 程序执行完成
✓ 连接已关闭

5. 代码解析

5.1 建立连接

javascript 复制代码
const taos = require("@tdengine/websocket");

// 配置连接参数
let url = 'ws://127.0.0.1:6041';  // taosAdapter 的 WebSocket 地址
let conf = new taos.WSConfig(url);
conf.setUser('root');              // 用户名
conf.setPwd('taosdata');           // 密码
conf.setDb('demo');                // 可选:指定默认数据库

// 建立连接
let wsSql = await taos.sqlConnect(conf);

连接参数说明:

  • url:WebSocket 地址,格式为 ws://host:port
  • user:数据库用户名,默认为 root
  • password:数据库密码,默认为 taosdata
  • database:可选,指定默认数据库

5.2 执行 SQL

Node.js 连接器提供两个主要方法:

执行非查询 SQL(exec) :用于执行 CREATEINSERTDROP 等不返回数据集的 SQL。

javascript 复制代码
let result = await wsSql.exec('CREATE DATABASE IF NOT EXISTS test');
console.log('影响的行数:', result.affectRows);
console.log('执行时长:', result.timing, 'ms');

执行查询 SQL(query) :用于执行 SELECT 等返回数据集的 SQL。

javascript 复制代码
let wsRows = await wsSql.query('SELECT * FROM meters');

// 获取列信息
let meta = wsRows.getMeta();

// 遍历结果
while (await wsRows.next()) {
    let row = wsRows.getData();
    console.log(row);
}

// 必须关闭结果集
await wsRows.close();

5.3 数据类型映射

TDengine 数据类型与 Node.js 类型的对应关系:

TDengine 类型 Node.js 类型 说明
TIMESTAMP bigint 时间戳(毫秒)
INT number 整数
BIGINT bigint 大整数
FLOAT number 单精度浮点
DOUBLE number 双精度浮点
BINARY string 二进制字符串
NCHAR string Unicode 字符串
BOOL boolean 布尔值
JSON string JSON 字符串

完整映射表见 API 参考文档

5.4 错误处理

使用 try-catch 捕获异常:

javascript 复制代码
try {
    await wsSql.exec('SELECT * FROM non_existent_table');
} catch (err) {
    console.error('错误信息:', err.message);
    console.error('错误码:', err.code);
}

常见错误码:

5.5 关闭连接

使用完连接后,务必关闭以释放资源:

javascript 复制代码
await wsSql.destroyed();

6. 进阶:参数绑定写入

参数绑定(Prepared Statement)可以显著提升批量写入性能,推荐用于高性能写入场景。

6.1 基本用法

javascript 复制代码
const taos = require("@tdengine/websocket");

async function stmtExample() {
    let wsSql = null;
    let stmt = null;

    try {
        // 建立连接
        let conf = new taos.WSConfig('ws://127.0.0.1:6041');
        conf.setUser('root');
        conf.setPwd('taosdata');
        wsSql = await taos.sqlConnect(conf);

        // 准备数据库和表
        await wsSql.exec('CREATE DATABASE IF NOT EXISTS demo');
        await wsSql.exec('USE demo');
        await wsSql.exec(
            'CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)'
        );

        // 1. 初始化 stmt 对象
        stmt = await wsSql.stmtInit();

        // 2. 准备 SQL(使用 ? 作为占位符)
        await stmt.prepare('INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)');

        // 3. 设置表名
        await stmt.setTableName('d1003');

        // 4. 设置 TAGS
        let tagsParams = new taos.StmtBindParams();
        tagsParams.setVarchar(['California.SanDiego']);
        tagsParams.setInt([3]);
        await stmt.setTags(tagsParams);

        // 5. 绑定数据(可以批量绑定多行)
        let bindParams = new taos.StmtBindParams();
        bindParams.setTimestamp([Date.now(), Date.now() + 1000]);
        bindParams.setFloat([10.8, 11.2]);
        bindParams.setInt([220, 221]);
        bindParams.setFloat([0.35, 0.36]);

        await stmt.bind(bindParams);

        // 6. 提交批次
        await stmt.batch();

        // 7. 执行写入
        await stmt.exec();

        console.log('写入条数:', stmt.getLastAffected());
    } catch (err) {
        console.error('错误:', err);
    } finally {
        // 关闭 stmt 和连接
        if (stmt) await stmt.close();
        if (wsSql) await wsSql.destroyed();
    }
}

stmtExample();

6.2 参数绑定的优势

  • 高性能:批量写入时性能可提升数倍
  • 防注入:避免 SQL 注入风险
  • 代码清晰:数据与 SQL 分离,更易维护

6.3 绑定类型方法

StmtBindParams 类提供了以下方法来绑定不同类型的数据:

javascript 复制代码
let params = new taos.StmtBindParams();

// 数值类型
params.setBoolean([true, false]);
params.setTinyInt([1, 2]);
params.setSmallInt([100, 200]);
params.setInt([1000, 2000]);
params.setBigint([10000n, 20000n]);
params.setFloat([1.1, 2.2]);
params.setDouble([1.111, 2.222]);

// 字符串类型
params.setVarchar(['hello', 'world']);
params.setBinary([Buffer.from('data1'), Buffer.from('data2')]);
params.setNchar(['中文', '测试']);

// 时间戳
params.setTimestamp([Date.now(), Date.now() + 1000]);

完整 API 参考见 参数绑定文档

7. 数据订阅(TMQ)

TDengine 支持数据订阅功能,类似 Kafka 的消息队列,可以实时消费写入的数据。

7.1 订阅示例

javascript 复制代码
const taos = require("@tdengine/websocket");

async function tmqExample() {
    let consumer = null;

    try {
        // 1. 创建消费者配置
        let configMap = new Map([
            [taos.TMQConstants.GROUP_ID, 'group1'],
            [taos.TMQConstants.CLIENT_ID, 'client1'],
            [taos.TMQConstants.WS_URL, 'ws://127.0.0.1:6041'],
            [taos.TMQConstants.CONNECT_USER, 'root'],
            [taos.TMQConstants.CONNECT_PASS, 'taosdata'],
            [taos.TMQConstants.AUTO_OFFSET_RESET, 'earliest'],
            [taos.TMQConstants.ENABLE_AUTO_COMMIT, 'true'],
            [taos.TMQConstants.AUTO_COMMIT_INTERVAL_MS, '1000']
        ]);

        // 2. 创建消费者
        consumer = await taos.newConsumer(configMap);

        // 3. 订阅主题(需要先在 TDengine 中创建主题)
        await consumer.subscribe(['topic_meters']);

        console.log('开始消费数据...');

        // 4. 循环拉取数据
        for (let i = 0; i < 10; i++) {
            let res = await consumer.poll(1000); // 超时时间 1000ms

            for (let [topic, taosResult] of res) {
                console.log(`主题: ${topic}`);
                let wsRows = taosResult;
                
                while (await wsRows.next()) {
                    console.log('数据:', wsRows.getData());
                }
                
                await wsRows.close();
            }
        }

        // 5. 提交消费位移
        await consumer.commit();
    } catch (err) {
        console.error('错误:', err);
    } finally {
        // 6. 关闭消费者
        if (consumer) {
            await consumer.unsubscribe();
            await consumer.close();
        }
    }
}

tmqExample();

7.2 创建主题

在使用订阅前,需要先在 TDengine 中创建主题:

sql 复制代码
-- 创建主题
CREATE TOPIC topic_meters AS SELECT * FROM demo.meters;

完整订阅 API 参考见 数据订阅文档

8. 常见问题排查

8.1 连接失败

症状

复制代码
Error: Unable to establish connection

原因和解决方案

  1. taosAdapter 未启动

    bash 复制代码
    # Linux/macOS
    systemctl start taosadapter
    systemctl status taosadapter
  2. 端口不正确

    • 默认 WebSocket 端口为 6041
    • 检查 taosAdapter 配置文件中的端口设置
  3. 防火墙阻止

    bash 复制代码
    # Linux 开放端口
    sudo firewall-cmd --zone=public --add-port=6041/tcp --permanent
    sudo firewall-cmd --reload
  4. 用户名或密码错误

    • 确认使用正确的用户名和密码
    • 默认用户名:root,密码:taosdata

8.2 FQDN 配置问题

症状

复制代码
Error: Unable to resolve FQDN

解决方案

确保 TDengine 服务端的 FQDN 配置正确。参考:

8.3 时区问题

症状:时间戳显示不正确。

解决方案

设置 taosAdapter 所在机器的 taosc 客户端时区配置:

bash 复制代码
# 在 taos.cfg 中设置
timezone=Asia/Shanghai

8.4 查询结果为空

检查项

  1. 确认数据已正确插入

    javascript 复制代码
    let result = await wsSql.exec('INSERT INTO d1001 VALUES (NOW, 10.3, 219, 0.31)');
    console.log('影响行数:', result.affectRows);
  2. 确认使用了正确的数据库

    javascript 复制代码
    await wsSql.exec('USE demo');
  3. 确认表名和列名拼写正确

8.5 Node.js 版本不兼容

症状

复制代码
Error: Package subpath './package.json' is not defined

解决方案

升级 Node.js 到 14 或更高版本:

bash 复制代码
node --version  # 检查当前版本
nvm install 18  # 使用 nvm 安装 Node.js 18
nvm use 18      # 切换到 Node.js 18

9. 最佳实践

9.1 连接管理

  1. 使用连接池:在高并发场景下,考虑实现连接池复用连接
  2. 及时关闭 :使用完连接后务必调用 destroyed() 释放资源
  3. 异常处理 :始终使用 try-catch-finally 确保连接被正确关闭
javascript 复制代码
async function withConnection(callback) {
    let wsSql = null;
    try {
        let conf = new taos.WSConfig('ws://127.0.0.1:6041');
        conf.setUser('root');
        conf.setPwd('taosdata');
        wsSql = await taos.sqlConnect(conf);
        
        return await callback(wsSql);
    } finally {
        if (wsSql) await wsSql.destroyed();
    }
}

// 使用
await withConnection(async (conn) => {
    await conn.exec('CREATE DATABASE IF NOT EXISTS test');
});

9.2 批量写入

使用参数绑定进行批量写入,可获得最佳性能:

javascript 复制代码
// 准备批量数据
let timestamps = [];
let currents = [];
let voltages = [];

for (let i = 0; i < 1000; i++) {
    timestamps.push(Date.now() + i * 1000);
    currents.push(Math.random() * 20);
    voltages.push(220 + Math.floor(Math.random() * 10));
}

// 批量绑定和写入
let params = new taos.StmtBindParams();
params.setTimestamp(timestamps);
params.setFloat(currents);
params.setInt(voltages);

await stmt.bind(params);
await stmt.batch();
await stmt.exec();

9.3 查询优化

  1. 限制返回数据量 :使用 LIMIT 子句

    javascript 复制代码
    let wsRows = await wsSql.query('SELECT * FROM meters LIMIT 1000');
  2. 使用时间范围过滤:利用时间索引提升性能

    javascript 复制代码
    let wsRows = await wsSql.query(
        "SELECT * FROM meters WHERE ts >= NOW - 1h"
    );
  3. 及时关闭结果集:遍历完成后立即关闭

    javascript 复制代码
    while (await wsRows.next()) {
        // 处理数据
    }
    await wsRows.close(); // 及时关闭

10. 更多资源

10.1 示例代码

GitHub 上的完整示例:

10.2 社区支持

11. 总结

通过本指南,你已经学会了:

✓ 安装和配置 Node.js 连接器

✓ 建立连接并执行基本 SQL 操作

✓ 使用参数绑定实现高性能写入

✓ 使用数据订阅功能

✓ 常见问题的排查和解决

下一步建议

  1. 阅读 完整 API 参考文档 了解更多高级功能
  2. 查看 GitHub 示例代码 学习实际应用
  3. Node.js 连接器 开源仓库地址
  4. 根据你的业务需求设计合适的数据模型
  5. 在生产环境中优化连接和查询性能

如有问题,欢迎在 GitHub 提交 Issue 或参与社区讨论!

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
90后小陈老师4 分钟前
PHP 配置默认值失效排查实录:isset 兜底遇上表单空串回填,首页文案是怎么集体消失的
开发语言·php
JJJennie7771 小时前
Gemini 3.7 Flash 上线,Google 想让 AI 多干活
开发语言·javascript·ecmascript
阿里云大数据AI技术2 小时前
Daft 多模态视频抽帧性能优化实践:从抽帧到大模型打标,一条视频理解流水线是怎么跑起来的
大数据·人工智能·spark
wuyk5552 小时前
Python 第三章:列表 List
服务器·开发语言·python
笨鸟先飞,勤能补拙2 小时前
从预测到决策:人工智能与机器学习的系统方法、工程闭环与现实边界
大数据·人工智能·windows·python·机器学习·密码学
tech讯息2 小时前
生成式 AI 从 POC 验证迈向正式生产,推理部署环节成为卡点的核心原因是什么?
大数据·人工智能
Aethir2 小时前
第三章 — 成本与经济模型
大数据·人工智能
Evand J2 小时前
【MATLAB例程,车联网7】CACC网联车辆协同控制:ACC对比、V2X时延丢包与队列稳定性,附例程下载链接
开发语言·matlab·车联网
逐米时代2 小时前
数智精益运营:量化验证让每个改善措施有数据说话
大数据
阿里云大数据AI技术2 小时前
免费领票!9月22日-24日,2026云栖大会杭州见
大数据·人工智能·agent