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 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
拓端研究室2 小时前
2026年人形机器人展望报告:市场趋势、技术创新与行业应用|附300+份报告PDF、数据、可视化模板汇总下载
大数据·人工智能·microsoft
脏脏a2 小时前
STL stack/queue 底层模拟实现与典型算法场景实践
开发语言·c++·stl_stack·stl_queue
烤麻辣烫2 小时前
Java开发手册规则精选
java·开发语言·学习
拓端研究室2 小时前
2026中国游戏产业趋势及潜力分析报告:小游戏、AI应用、出海趋势|附160+份报告PDF、数据、可视化模板汇总下载
大数据·人工智能
APItesterCris2 小时前
商品详情 API 的签名验证与安全接入技术要点
大数据·数据库·安全·架构
达瓦里氏1232 小时前
一文厘清:医疗器械一类、二类、三类的划分逻辑
大数据·健康医疗
DYS_房东的猫2 小时前
《 C++ 零基础入门教程》第8章:多线程与并发编程 —— 让程序“同时做多件事”
开发语言·c++·算法
余道各努力,千里自同风2 小时前
node.js 操作 MongoDB
数据库·mongodb·node.js
ekkcole2 小时前
java实现对excel模版填充保存到本地后合并单元格并通过网络下载
java·开发语言·excel