- 向量数据库
- 数据库
- 人工智能
- 后端
【免费下载链接】lancedb
Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.
本篇文章以 LanceDB 官方 JavaScript SDK(@lancedb/lancedb)为主线,系统讲解如何在 Node.js 应用中完成安装、建立连接、创建/写入数据表、执行向量检索与全文搜索,并结合仓库源码剖析connect、createTable、vectorSearch等核心 API 的底层实现与调用链。读完本文,你将能够从零搭建一个可运行的嵌入式向量检索应用,并具备深入阅读 SDK 源码、二次开发与调试的能力。
LanceDB JavaScript SDK 概览
LanceDB 是一个面向多模态 AI 场景的开发者友好型开源嵌入式向量数据库,其核心价值在于"少管理、多检索"(Search More; Manage Less):无需独立部署数据库服务,直接在应用进程内以库的形式运行。JavaScript SDK 则是 LanceDB 在 Node.js/TypeScript 生态中的官方接入层,包名为@lancedb/lancedb(见 nodejs/package.json)。
从源码结构看,该 SDK 采用Rust 核心 + napi-rs 绑定的架构:
nodejs/src/:Rust 绑定层源码,负责与 LanceDB 核心库交互;nodejs/lancedb/:TypeScript 包源码,面向开发者的公开 API 全部从这里导出;nodejs/__test__/:单元测试(基于 Jest);nodejs/examples/:文档配套的可运行示例(pnpm workspace)。
这一架构意味着:所有重计算(索引构建、向量距离计算、列式存储读写)都发生在原生层,而 JS 层负责提供类型安全的、Promise 化的开发体验。入口文件 nodejs/lancedb/index.ts 一次性导出了连接、表、查询、索引、嵌入函数、重排序(rerankers)、物化视图等全部公开类型与函数,是理解整个 SDK 能力边界的起点。
环境要求与安装
安装命令
npm install @lancedb/lancedb安装时 npm 会自动下载与你当前平台匹配的原生库(每个平台发布为独立的 npm 包,见 nodejs/npm/ 下的darwin-arm64、linux-x64-gnu、win32-x64-msvc等目录)。当前仓库支持的平台包括:
- Linux:x86_64 与 aarch64,同时支持 glibc 与 musl;
- macOS:Intel(x86_64)与 Apple Silicon(ARM/M1/M2,aarch64);
- Windows:x86_64 与 aarch64。
与 nodejs/package.json 中napi.targets声明的编译目标一一对应,即aarch64-apple-darwin、x86_64-unknown-linux-gnu、aarch64-unknown-linux-gnu、x86_64-unknown-linux-musl、aarch64-unknown-linux-musl、x86_64-pc-windows-msvc、aarch64-pc-windows-msvc。
运行环境约束
根据 nodejs/package.json 中的声明,使用时还需注意:
- Node.js 版本:
engines.node >= 22; - Apache Arrow:作为 peerDependency,要求
apache-arrow >= 15.0.0 且 <= 18.1.0(SDK 与 Arrow 数据格式深度耦合,Arrow 数据、Schema、RecordBatch 都直接来自该库); - 可选依赖:
openai(OpenAI 嵌入函数)与@huggingface/transformers(本地 Transformers 嵌入函数)按需安装即可; - 包管理器在仓库内使用 pnpm 11(
packageManager: pnpm@11.1.1),发布版本为0.40.0-beta.5,License 为 Apache-2.0。
快速上手:从连接到向量搜索
nodejs/README.md 给出了一个最小可运行的完整示例,这是理解 SDK 用法的最佳起点:
import * as lancedb from "@lancedb/lancedb"; // 1. 连接:创建(或打开)本地数据库目录 const db = await lancedb.connect("data/sample-lancedb"); // 2. 建表:用普通 JS 对象数组初始化一张表,自动推导 schema const table = await db.createTable("my_table", [ { id: 1, vector: [0.1, 1.0], item: "foo", price: 10.0 }, { id: 2, vector: [3.9, 0.5], item: "bar", price: 20.0 }, ]); // 3. 向量搜索:返回与查询向量最相似的 20 条记录 const results = await table.vectorSearch([0.1, 0.3]).limit(20).toArray(); console.log(results);这个例子覆盖了 SDK 的三个核心动作:
connect(uri)—— 建立数据库连接。传入本地目录路径时即创建嵌入式数据库;createTable(name, data)—— 以普通对象数组建表。SDK 会将数据转换为 Arrow IPC 格式交给原生层(parseTableData与fromTableToBuffer,见 nodejs/lancedb/connection.ts),字段vector会被识别为向量列;vectorSearch(vector)—— 发起近似最近邻(ANN)检索,返回包含原始字段与距离的匹配行。
源码视角:vectorSearch 到底做了什么
vectorSearch是Table上的便捷方法,其实现位于 nodejs/lancedb/table.ts:
vectorSearch(vector: IntoVector | MultiVector): VectorQuery { if (isMultiVector(vector)) { const query = this.query().nearestTo(vector[0]); for (const v of vector.slice(1)) { query.addQueryVector(v); } return query; } return this.query().nearestTo(vector); }可以看到它内部委托给query().nearestTo(vector),构建一个VectorQuery查询构建器(见 nodejs/lancedb/query.ts)。VectorQuery支持链式调用.limit()、.select()、.offset()、.filter()、.distanceType()等,最后通过.toArray()(或.toArrow()、异步迭代RecordBatch)触发执行。
测试用例 nodejs/test/query.test.ts 验证了向量搜索返回的 schema 中除所选列外还会追加一个_distance字段(Float32 类型),用于表示每条结果与查询向量的距离;同时验证了offset是在limit之后应用的,可据此实现稳定的分页:
// 第二页:先取前 4 条再跳过 2 条 const secondPage = await table .vectorSearch([0, 0]) .select(["id"]) .limit(2) .offset(2) .toArray();连接管理:URI 格式、选项与多种连接方式
connect的完整签名与实现位于 nodejs/lancedb/index.ts。它支持两种调用形式:
// 形式一:connect(uri, options?, session?, headerProvider?) const conn = await lancedb.connect("/path/to/database"); const conn2 = await lancedb.connect("s3://bucket/path/to/database", { storageOptions: { timeout: "60s" }, }); // 形式二:connect(options & { uri }) const conn3 = await lancedb.connect({ uri: "/path/to/database", session: Session.default(), });支持的 URI 格式
/path/to/database—— 本地文件系统数据库;s3://bucket/path或gs://bucket/path—— 云对象存储上的数据库(通过storageOptions传入访问凭证、超时等配置);db://host:port—— 远程数据库(LanceDB Cloud),此时可配合headerProvider做每请求鉴权(例如StaticHeaderProvider注入X-API-Key)。
内部实现上,connect会通过LanceDbConnection.new(uri, finalOptions, nativeProvider)创建原生连接,再包装成LocalConnection返回(见 nodejs/lancedb/connection.ts)。
storageOptions 的规范化
传入的存储选项会经过cleanseStorageOptions处理(nodejs/lancedb/connection.ts):所有键会被统一转换为 snake_case后再传给原生层。因此你既可以用{ timeout: "60s" }也可以用{ "timeout": "60s" },SDK 会保证兼容。
connectNamespace:目录 / REST 命名空间 / 自定义实现
除按 URI scheme 路由的connect外,SDK 还提供connectNamespace(implName, config, options?)(nodejs/lancedb/index.ts),用于通过命名空间实现连接:
"dir"—— 目录命名空间,配置{ root: "/path/to/db", manifestEnabled?, extraProperties? },所有表存放于单一根路径下;"rest"—— REST 目录服务,配置{ uri: "https://catalog.example.com", headers?, extraProperties? },通过 HTTP 访问远端 catalog;- 其他字符串 —— 自定义命名空间实现的完整模块路径,配置为自由格式的
properties字符串映射。
连接生命周期
Connection是一个长生命周期对象,可能持有 HTTP 连接池等资源,官方建议在多次使用中共享同一个连接。完成使用后可调用close()主动释放资源;不关闭也会在垃圾回收时自动清理。连接关闭后再调用其方法会直接报错。此外,已创建的表是独立对象,即使底层连接被关闭,表仍可继续工作(见 nodejs/lancedb/connection.ts 中Connection类文档)。
建表与数据写入
createTable 的多种重载与选项
createTable支持多种重载形式(名称+数据、options 对象、命名空间路径),公共选项见CreateTableOptions(nodejs/lancedb/connection.ts):
| 选项 | 类型 | 说明 |
|---|---|---|
mode | "create" \| "overwrite" | "create"时若表已存在则报错(除非existOk为 true);"overwrite"直接替换已有表 |
existOk | boolean | 表已存在且 mode 为"create"时不报错(内部转换为"exist_ok") |
schema | SchemaLike | 显式指定 schema,替代自动推导 |
embeddingFunction | EmbeddingFunctionConfig | 配置自动嵌入函数,写入时自动生成向量 |
storageOptions | Record<string, string> | 对象存储配置,继承连接配置但可覆盖 |
dataStorageVersion/enableV2ManifestPaths | 已废弃 | 分别迁移到newTableDataStorageVersion与newTableEnableV2ManifestPaths存储选项 |
值得注意的实现细节:在LocalConnection.createTable(_createTableImpl)中,dataStorageVersion与enableV2ManifestPaths这两个已废弃字段会被自动改写进 storageOptions(见 nodejs/lancedb/connection.ts),保证向后兼容。
创建空表与增量写入
// 创建空表(需要显式 schema) await db.createEmptyTable("empty_table", schema); // 增量写入:追加 or 覆盖 const result = await table.add(newRows); // 默认 append const result2 = await table.add(newRows, { mode: "overwrite" }); // 监听写入进度 await table.add(data, { progress: (p) => { console.log(`${p.outputRows}/${p.totalRows ?? "?"} rows`); }, });AddDataOptions的progress回调(nodejs/lancedb/table.ts)会按批次触发,并在结束时以done: true回调一次;回调异常只会console.warn记录而不会中断写入。add返回的AddResult包含新的表版本号。
此外,Table还提供update(支持 SQL 条件where、values与valuesSql)、delete、mergeInsert(MergeInsertBuilder)等数据变更能力,均返回包含影响行数与版本号的 Result 对象。
表管理:打开、列举、删除与命名空间
打开与分页列举
// 打开表,可选 branch(分支)与 version(版本钉定) const table = await db.openTable("my_table", { branch: "feature-branch", version: 42, // 只读视图,配合 checkoutLatest 恢复可写 }); // 分页列举表(pageToken 为不透明令牌) const names: string[] = []; let pageToken = undefined; do { const page = await conn.listTables({ pageToken, limit: 100 }); names.push(...page.tables); pageToken = page.pageToken; } while (pageToken);openTable的实现(nodejs/lancedb/connection.ts)会先打开表,再根据branch/version选项自动执行分支检出或版本钉定;"main"被视为默认分支从而跳过额外操作。
删除与清理
dropTable(name):同步删除;dropTableAsync(name):返回Job,可等待物理文件清理完成(表可能在清理完成前就已不可用);dropAllTables():清空数据库。
Job是 SDK 中异步后台任务的一等公民:Connection还提供openJob(jobId)、listJobs()、cancelJob(jobId)来追踪服务端任务状态。
命名空间(Namespace)
命名空间用于对表进行层级组织,相关 API 全部在Connection上:
createNamespace(path, { mode: "create" | "exist_ok" | "overwrite", properties });listNamespaces(path?, { pageToken, limit })、describeNamespace(path);dropNamespace(path, { mode: "skip" | "fail", behavior: "restrict" | "cascade" })——"restrict"拒绝删除非空命名空间,"cascade"递归删除其中所有内容。
克隆与重命名
cloneTable(targetName, sourceUri, options)支持浅克隆(默认isShallow: true):新表与源表共享底层数据文件,但拥有独立 manifest,可各自演进。renameTable则目前仅 LanceDB Cloud 支持,本地连接与命名空间连接会返回 "not supported" 错误(见Connection类文档)。
检索:向量搜索、全文搜索与查询构建器
查询构建器通用能力
QueryBase(nodejs/lancedb/query.ts)是所有查询(Query/VectorQuery/TakeQuery)的公共基类,提供:
select(...):投影所需列,显著降低列式存储的 I/O 延迟;也支持动态列,如new Map([["combined", "a + b"]])(SQL 表达式)——这是官方建议的实践;limit(n)/offset(n):分页(注意 offset 在 limit 之后应用,见测试用例);orderBy(...):按列排序(支持升降序与 null 优先级);filter(expr):SQL 过滤表达式;distanceType(type):向量距离度量(默认"l2";nodejs/lancedb/indices.ts 中特别强调:索引训练时使用的距离类型必须与检索时一致,否则结果不准确);- 终端操作:
.toArray()返回行对象数组;查询对象本身也是AsyncIterable<RecordBatch>,可用for await逐批消费,并通过QueryExecutionOptions(maxBatchLength、timeoutMs)控制执行。
向量检索与全文检索
// 向量检索(自动追加 _distance 列) await table.vectorSearch([0.1, 0.3]).limit(20).toArray(); // 全文检索:先创建 FTS 索引 await table.createIndex("text", { config: Index.fts() }); await table.search("foo", "fts").select(["id"]).limit(10).toArray();全文检索结果会附带_score字段(由 nodejs/test/query.test.ts 的 schema 断言确认)。FTS 索引支持 tokenizer 配置(simple等基础分词器、语言、停用词、词干化、ngram 等),Table还导出tokenize函数,可在不建索引的情况下直接分词(见 nodejs/lancedb/index.ts 的TokenizeOptions)。
search() 的自动路由
Table.search(query, queryType = "auto")(nodejs/lancedb/table.ts)会根据参数自动路由:
- 传入向量 → 走
vectorSearch; queryType: "fts"→ 走全文搜索;queryType: "auto"且表配置了嵌入函数 → 由嵌入函数计算查询向量后执行向量检索(computeQueryEmbeddings)。
对于多向量混合检索,SDK 还提供了rerankers模块(如RRFReranker,见 nodejs/lancedb/rerankers/rrf.ts),用于融合多路检索结果。
索引:让检索从暴力扫描走向 ANN
Table.createIndex配合Index工厂(nodejs/lancedb/indices.ts)可创建多种索引:
Index.ivfPq(options):IVF + 乘积量化,最常用的 ANN 索引,关键参数:numPartitions:IVF 分区数,默认取行数的平方根;过大则选分区慢,过小则分区内搜索慢;numSubVectors:PQ 子向量数,控制压缩率,默认dim / 16(不可整除时dim / 8,以便利用 SIMD 指令);numBits:每个子向量的量化位数,必须为 4 或 8,默认 8;distanceType:距离度量,默认"l2",必须与检索一致;
Index.hnswSq(options)/Index.hnswPq(options):基于 HNSW 的图索引;Index.fts(options):全文索引,支持 tokenizer 与语言配置;Index.ivfFlat/Index.ivfRq:其他向量索引变体。
索引构建是异步任务,可用Job追踪进度。数据集较大时合理选择numPartitions与量化位数,是在召回率与延迟之间做权衡的关键(索引配置的完整类型见 nodejs/lancedb/indices.ts 的IvfPqOptions等接口)。
自动嵌入:Embedding 注册表与内置嵌入函数
SDK 提供了一等公民的嵌入函数体系,让"写入时自动生成向量、检索时自动嵌入查询"成为可能:
nodejs/lancedb/embedding/目录下内置了openai.ts(OpenAI 嵌入模型)与transformers.ts(本地 HuggingFace Transformers 模型);- 所有嵌入函数继承自抽象的
EmbeddingFunction(nodejs/lancedb/embedding/embedding_function.ts),实现computeQueryEmbeddings/ 文本编码等接口; - 通过
EmbeddingFunctionRegistry注册/查找函数,注册信息(含函数配置)会序列化到表元数据中,检索时可自动解析并路由。
使用方式是在建表时声明embeddingFunction:
import * as lancedb from "@lancedb/lancedb"; import { getRegistry } from "@lancedb/lancedb/embedding"; // 或使用内置的 openai / transformers 嵌入函数 const db = await lancedb.connect("data/sample-lancedb"); const table = await db.createTable("documents", [ { text: "hello world", category: "greeting" }, ], { embeddingFunction: /* 注册表返回的嵌入函数配置 */, }); // 之后 table.search("任意文本") 会自动完成嵌入与检索从createEmptyTable的实现可以看到,embeddingFunction会通过registry.getTableMetadata生成表元数据(nodejs/lancedb/connection.ts),而search(..., "auto")则通过registry.parseFunctions从元数据还原嵌入函数并计算查询向量——正是这两段代码构成了"自动嵌入"的闭环。
本地开发与测试
如果你想在仓库内对 SDK 进行二次开发或运行测试,nodejs/CONTRIBUTING.md 说明了完整流程。前置条件:Node.js 22+、pnpm 11+(或corepack enable)、Rust 工具链(rustup 安装 Cargo)、以及 protoc(Protocol Buffers 编译器)。
pnpm install # 安装依赖 pnpm build # 构建原生绑定 + 编译 TypeScript pnpm lint # Biome 检查与格式化 pnpm test # 运行全部 Jest 测试 # 运行单个测试文件 pnpm test -- table.test.ts # 按名称过滤用例 pnpm test -- table.test.ts --testNamePattern=merge\ insert构建脚本(见 nodejs/package.json 的scripts)使用napi build产出平台原生.node文件并生成native.d.ts/native.js,TypeScript 层通过lancedb/native.js与原生模块桥接——这也是理解"JS 方法 → 原生调用"链路的关键入口。
总结
LanceDB JavaScript SDK 以"嵌入式、零运维"的方式把向量数据库能力带入了 Node.js 生态:connect一行完成连接、createTable用普通对象数组建表、vectorSearch链式调用完成 ANN 检索,全程无需管理任何服务进程。在此基础上,本文进一步结合仓库源码剖析了connect的 URI 路由与 options 规范化、vectorSearch到nearestTo的委托链路、createTable的多种模式与选项、分页/命名空间/物化视图等表管理能力,以及索引参数与自动嵌入函数的底层机制。若需查看更多完整示例,可继续阅读 nodejs/README.md、docs/src/js/README.md 与 nodejs/examples/ 中的可运行代码,或直接阅读 nodejs/test/ 下的测试用例验证各 API 的实际行为。
- 向量数据库
- 数据库
- 人工智能
- 后端
【免费下载链接】lancedb
Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.
相关推荐
LanceDB JavaScript SDK 完整使用指南:安装、向量检索与表管理实战
LanceDB JavaScript SDK 完整使用指南:安装、向量检索与表管理实战 本篇技术指南以仓库文档 docs/src/js/README.md ht
向量数据库数据库人工智能后端LLM Zoomcamp 向量搜索实战:使用 minsearch 构建内存向量索引与语义检索
LLM Zoomcamp 向量搜索实战:使用 minsearch 构建内存向量索引与语义检索 在本篇技术指南中,我们将围绕 LLM Zoomcamp(2026
示例工程教程人工智能大模型LanceDB Rust SDK 实战指南:用 Rust 构建嵌入式向量检索与多模态 AI 应用
LanceDB Rust SDK 实战指南:用 Rust 构建嵌入式向量检索与多模态 AI 应用 LanceDB Rust SDK(crate 名为 lance
向量数据库数据库人工智能后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考