LanceDB Node.js 全文检索分词:TokenizeTableOptions 类型别名详解
2026/9/23 23:55:22 网站建设 项目流程
  • 向量数据库
  • 数据库
  • 人工智能
  • 后端

【免费下载链接】lancedb

Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.

项目地址:https://gitcode.com/gh_mirrors/la/lancedb
点击查看免费下载

TokenizeTableOptions是 LanceDB Node.js 客户端中用于全文检索(Full-Text Search, FTS)查询分词的参数类型。它定义了两个互斥的分词器定位方式——按 FTS 索引所属列(column)或按 FTS 索引名称(indexName)指定要复用的分词器,供Table.tokenize()方法使用。读完本文,你将掌握该类型别名的完整定义、二选一约束的底层校验逻辑、与 FTS 索引配置的对应关系,以及如何通过测试用例验证其行为。

一、类型定义:两种互斥形态

该文档对应的类型别名定义位于 nodejs/lancedb/table.ts:

export type TokenizeTableOptions = | { /** FTS-indexed column whose tokenizer should be used. */ column: string; indexName?: never; } | { /** Name of the FTS index whose tokenizer should be used. */ indexName: string; column?: never; };

这是一个 TypeScript 联合类型,两个分支分别对应:

形态必填字段说明
按列指定column: string使用该列上 FTS 索引配置的分词器
按索引名指定indexName: string使用该名称 FTS 索引配置的分词器

两个分支都通过?: never将另一字段声明为"禁止出现":即调用时必须且只能指定columnindexName中的一个。这种类型级约束在编译期就能拦截错误用法——如果同时传两个字段,TypeScript 会直接报类型错误。

二、使用场景:Table.tokenize() 方法

TokenizeTableOptionsTable.tokenize()方法的第二个参数类型。该方法的抽象签名位于 nodejs/lancedb/table.ts:

/** * Tokenize a full-text search query using the tokenizer configured on an FTS index. * * Specify exactly one of `column` or `indexName`. */ abstract tokenize( query: string, options: TokenizeTableOptions, ): Promise<FtsToken[]>;

其实际实现(nodejs/lancedb/table.ts)将columnindexName作为两个独立参数透传给底层原生层:

async tokenize( query: string, options: TokenizeTableOptions, ): Promise<FtsToken[]> { return await this.inner.tokenize( query, options?.column, options?.indexName, ); }

典型调用方式:

import { connect } from "@lancedb/lancedb"; const db = await connect("./data"); const table = await db.openTable("my_table"); // 方式一:按列名指定,复用该列 FTS 索引的分词器 const tokens1 = await table.tokenize("Running in cafés", { column: "text", }); // 方式二:按索引名称指定,复用该 FTS 索引的分词器 const tokens2 = await table.tokenize("Hello, こんにちは世界!", { indexName: "japanese_icu_idx", });

返回值FtsToken[]中的每个 token 包含text(经分词器过滤后的 token 文本)与position(全文检索匹配使用的 token 位置)两个字段,其定义同样位于 nodejs/lancedb/table.ts。

三、底层实现:参数互斥校验

Node.js 层通过 N-API 绑定调用 Rust 核心实现。Rust 侧tokenize方法位于 nodejs/src/table.rs:

pub async fn tokenize( &self, query: String, column: Option<String>, index_name: Option<String>, ) -> napi::Result<Vec<FtsToken>> { let table = self.inner_ref()?; let tokens = match (column.as_deref(), index_name.as_deref()) { (Some(_), Some(_)) | (None, None) => { return Err(napi::Error::from_reason( "Specify exactly one of 'column' or 'indexName'", )); } (Some(column), None) => table.tokenize_with_column(&query, column).await, (None, Some(index_name)) => table.tokenize(&query, index_name).await, } .default_error()?; Ok(tokens.into_iter().map(FtsToken::from).collect()) }

从源码结构可以看出:

  • 运行时兜底校验:类型层面的?: never约束只在编译期生效,运行时仍会检查(Some, Some)(同时传入)和(None, None)(都没传)两种非法组合,并抛出错误信息"Specify exactly one of 'column' or 'indexName'"。这意味着即使绕过 TypeScript 类型检查(例如通过as never断言或纯 JavaScript 调用),错误用法也会在运行时被拦截。
  • 两条执行路径:传入column时走tokenize_with_column路径,从列关联的 FTS 索引读取分词器配置;传入indexName时走tokenize路径,直接按索引名定位。

四、行为验证:测试用例佐证

仓库测试 nodejs/test/table.test.ts 完整验证了该类型的行为,包括非法参数的运行时错误与两种合法用法的分词结果:

// 什么都不传 -> 报错 await expect(table.tokenize("hello", {} as never)).rejects.toThrow( "Specify exactly one", ); // 同时传 column 和 indexName -> 报错 await expect( table.tokenize("hello", { column: "text", indexName: "text_idx", } as never), ).rejects.toThrow("Specify exactly one"); // 按 column 指定:simple 分词器(带词干还原) const simpleTokens = await table.tokenize("Running in cafés", { column: "text", }); expect(simpleTokens).toEqual([ { text: "run", position: 0 }, { text: "cafe", position: 2 }, ]); // 按 indexName 指定:icu 分词器(支持日文分词) const icuTokens = await table.tokenize("Hello, こんにちは世界!", { indexName: "japanese_icu_idx", }); expect(icuTokens).toEqual([ { text: "hello", position: 0 }, { text: "こんにちは", position: 1 }, { text: "世界", position: 2 }, ]);

该测试揭示了两个关键事实:

  1. 分词结果与索引配置强相关simple分词器会做词干还原(Runningruncaféscafe),而icu分词器支持基于字典的日文分词(こんにちは世界被正确切分为こんにちは世界)。
  2. position 记录的是分词序列中的位置insimple分词器当作停用词移除后,cafe的 position 为 2,说明 position 基于分词后的序列而非原文词序。

五、与 FTS 索引分词器配置的对应关系

columnindexName指向的 FTS 索引,其分词器由创建索引时的FtsOptions配置决定。在 nodejs/lancedb/indices.ts 中,FtsOptions.baseTokenizer支持以下取值:

  • "simple":以空白和标点作为分隔符切分文本(默认值),通常配合词干还原与停用词过滤;
  • "whitespace":仅以空白作为分隔符;
  • "raw":不切分文本,将整段文本作为单个 token 索引;
  • "ngram":按 n-gram 切分,可配合ngramMinLengthngramMaxLengthprefixOnly使用;
  • "icu":基于 ICU 字典的词分割;
  • "icu/split":ICU 分割 + 简单式分隔符切分;
  • `jieba/${string}``lindera/${string}`:基于模型的分词器(如中文分词)。

此外,FtsOptions还支持language(词干还原与停用词语言)、lowercasestemremoveStopWordscustomStopWordsmaxTokenLengthasciiFolding等分词过滤配置。创建 FTS 索引示例:

await table.createIndex("text", { config: Index.fts({ baseTokenizer: "simple" }), }); await table.createIndex("japanese", { config: Index.fts({ baseTokenizer: "icu", stem: false, removeStopWords: false, }), name: "japanese_icu_idx", });

这也解释了为什么tokenize()无需显式传入分词器类型——分词器配置已经固化在索引元数据中,TokenizeTableOptions只需定位到索引即可。

六、使用注意事项

  1. 模型型分词器的本地依赖:从Table.tokenize()的文档注释(nodejs/lancedb/table.ts)可以确认,jieba/*lindera/*这类模型型分词器会在客户端进程内根据索引元数据重建。对于远程表,意味着本地也必须存在相同的分词器模型文件,否则无法完成分词。
  2. 编译期与运行期双重约束:TS 类型层面通过?: never保证二选一,运行时 Rust 层再次校验,二者共同保证参数使用的正确性。
  3. 先建索引再分词tokenize()依赖已存在的 FTS 索引获取分词器配置,因此调用前需确保目标列或索引名对应的 FTS 索引已通过createIndex创建。

相关资源

  • 类型别名定义:nodejs/lancedb/table.ts
  • 调用方方法签名与文档:nodejs/lancedb/table.ts
  • 返回值类型FtsToken:nodejs/lancedb/table.ts
  • Rust 侧实现与参数校验:nodejs/src/table.rs
  • 测试用例:nodejs/test/table.test.ts
  • FTS 索引与分词器配置:nodejs/lancedb/indices.ts
  • 向量数据库
  • 数据库
  • 人工智能
  • 后端

【免费下载链接】lancedb

Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.

项目地址:https://gitcode.com/gh_mirrors/la/lancedb
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询