LanceDB Node.js 全文检索 BooleanQuery 指南:用 Occur 组合子查询构建精准 FTS 查询
2026/9/23 12:16:08 网站建设 项目流程

LanceDB Node.js 全文检索 BooleanQuery 指南:用 Occur 组合子查询构建精准 FTS 查询

【免费下载链接】lancedbDeveloper-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.项目地址: https://gitcode.com/gh_mirrors/la/lancedb

BooleanQuery 是 LanceDB Node.js SDK(@lancedb/lancedb)中用于组合全文检索(Full-Text Search, FTS)子查询的类。本文将深入讲解它的构造方式、Occur出现语义(Must / Should / MustNot)与queryType()方法,并结合 query.ts 的源码实现与 table.test.ts 中的真实测试用例,演示如何用它实现"必须包含 A、可以包含 B、不能包含 C"这类复杂检索需求。

1. BooleanQuery 是什么

从类型体系上看,BooleanQuery实现了FullTextQuery接口(见 FullTextQuery 接口文档),是 LanceDB FTS 查询家族的成员之一。它本身不直接执行搜索,而是把若干个子查询按照布尔出现语义组合成一个复合查询对象,再交给Table.search()执行。

在 query.ts 中可以看到其完整定义:

export class BooleanQuery implements FullTextQuery { /** @ignore */ public readonly inner: JsFullTextQuery; constructor(queries: [Occur, FullTextQuery][]) { this.inner = JsFullTextQuery.booleanQuery( queries.map(([occur, query]) => [occur, query.inner]), ); } queryType(): FullTextQueryType { return FullTextQueryType.Boolean; } }

MatchQueryPhraseQueryBoostQueryMultiMatchQuery一样,BooleanQuery通过inner字段持有底层原生查询对象(napi 绑定中的JsFullTextQuery),并在构造时把每个子查询的inner解包后一并传给原生层。

2. 构造函数:queries 参数与 Occur 语义

BooleanQuery的构造函数签名如下:

new BooleanQuery(queries): BooleanQuery

其中:

  • queries[Occur, FullTextQuery][],即一组"出现语义 + 子查询"的二元组数组。Occur决定该子查询在整体匹配中的权重与约束,子查询可以是MatchQueryPhraseQueryMultiMatchQueryBoostQuery甚至嵌套的BooleanQuery

2.1 Occur 枚举:MUST / SHOULD / MUST_NOT

Occur枚举定义在 query.ts,其语义对应 Lucene 风格的布尔查询:

成员语义
Should"SHOULD"子查询匹配时计入相关性得分,但不是必须匹配
Must"MUST"子查询必须匹配,否则文档不会进入结果集
MustNot"MUST_NOT"子查询必须不匹配,匹配则该文档被排除

三种语义组合起来就能表达绝大多数布尔检索需求:

  • Must + Must:所有条件都满足(逻辑 AND);
  • Should + Should:至少一个条件满足即可(逻辑 OR,并影响得分排序);
  • Must + MustNot:满足 A 且不满足 B(排除式过滤)。

完整枚举定义可参考 Occur 枚举文档。

2.2 子查询类型:FullTextQueryType

BooleanQueryqueryType()固定返回FullTextQueryType.Boolean(值为"boolean")。整个FullTextQueryType枚举(FullTextQueryType 枚举文档)如下:

export enum FullTextQueryType { Match = "match", MatchPhrase = "match_phrase", Boost = "boost", MultiMatch = "multi_match", Boolean = "boolean", }

也就是说,一个BooleanQuery内部可以自由混合MatchQuerymatch)、PhraseQuerymatch_phrase)、BoostQueryboost)和MultiMatchQuerymulti_match)等任意子查询类型,从而构造出层级化的查询树。

3. 源码级原理:从 TypeScript 到原生查询

BooleanQuery只是门面,真正的组合逻辑发生在 Rust 侧。在 nodejs/src/query.rs 中,napi 工厂方法boolean_query接收Vec<(String, &JsFullTextQuery)>(即从 TypeScript 传入的[Occur 字符串值, 子查询对象]列表),逐个把Occur字符串解析为 Rust 枚举,再克隆子查询的inner

pub fn boolean_query(queries: Vec<(String, &JsFullTextQuery)>) -> napi::Result<Self> { let mut sub_queries = Vec::with_capacity(queries.len()); for (occur, q) in queries { let occur = Occur::try_from(occur.as_str()) .map_err(|e| napi::Error::from_reason(e.to_string()))?; sub_queries.push((occur, q.inner.clone())); } Ok(Self { inner: BooleanQuery::new(sub_queries).into(), }) }

从源码结构可以看出:

  • Occur的字符串值("SHOULD""MUST""MUST_NOT")是跨语言传递的契约,TypeScript 层与 Rust 层必须保持一致;
  • 每个子查询在进入 Rust 层前先通过query.inner解包,因此子查询可以是任意FullTextQuery实现,包括嵌套的BooleanQuery
  • 底层BooleanQuery::new直接构造复合查询对象,随后在真正的 FTS 执行器(tantivy 引擎)中按Occur语义求值。

4. 实战示例:把 BooleanQuery 用于 Table.search()

BooleanQuery的典型用法是将其作为Table.search()的参数。Query.fullTextSearch()Query.nearestToText()都接受string | FullTextQuery,当传入BooleanQuery这类对象时,SDK 会走"结构化查询"分支(见 query.ts),把查询对象整体交给原生层,而不是把字符串当作普通词项处理。

下面是一个完整可运行的示例(数据与断言改编自仓库测试 table.test.ts):

import { connect, Index, BooleanQuery, Occur, MatchQuery } from "@lancedb/lancedb"; const db = await connect("/tmp/lancedb-boolean-demo"); const data = [ { text: "The cat and dog are playing" }, { text: "The cat is sleeping" }, { text: "The dog is barking" }, { text: "The dog chases the cat" }, ]; const table = await db.createTable("test", data); // FTS 需要先在目标列上创建全文索引 await table.createIndex("text", { config: Index.fts({ withPosition: false }), }); // 1) SHOULD + SHOULD:命中 cat 或 dog 的文档都返回(逻辑 OR) const shouldResults = await table .search( new BooleanQuery([ [Occur.Should, new MatchQuery("cat", "text")], [Occur.Should, new MatchQuery("dog", "text")], ]), ) .toArray(); // 4 条文档全部命中(4 条里要么含 cat 要么含 dog) // 2) MUST + MUST:同时包含 cat 和 dog 的文档才返回(逻辑 AND) const mustResults = await table .search( new BooleanQuery([ [Occur.Must, new MatchQuery("cat", "text")], [Occur.Must, new MatchQuery("dog", "text")], ]), ) .toArray(); // 命中 "The cat and dog are playing" 和 "The dog chases the cat",共 2 条 // 3) MUST + MUST_NOT:包含 cat 但不包含 dog 的文档才返回 const mustNotResults = await table .search( new BooleanQuery([ [Occur.Must, new MatchQuery("cat", "text")], [Occur.MustNot, new MatchQuery("dog", "text")], ]), ) .toArray(); // 命中 "The cat is sleeping",共 1 条

4.1 关键使用前提

  • 必须先建 FTS 索引:对text列执行createIndex并配置Index.fts(...)后,全文检索(含布尔组合)才能工作;
  • 子查询必须落在同一类查询语义上MatchQuery构造时的column参数指定检索列,布尔组合通常针对同一文本列进行;
  • 结果仍走.toArray()/ 迭代器search()返回链式Query对象,最终通过.toArray()或异步迭代消费结果,与普通 FTS 一致。

5. 在查询家族中的位置

BooleanQuery不是孤立存在的,它与另外四个查询类共同构成FullTextQuery体系,全部定义在 query.ts 中,并从 index.ts 对外导出:

  • MatchQuerymatch):单列词项检索,支持boostfuzzinessmaxExpansionsoperatorprefixLength
  • PhraseQuerymatch_phrase):精确短语检索,支持slop
  • BoostQueryboost):正/负查询加权,negativeBoost控制负查询惩罚力度;
  • MultiMatchQuerymulti_match):跨多列检索,支持逐列boosts
  • BooleanQueryboolean):用Occur组合上述任意查询。

由于FullTextQuery接口只要求实现queryType()并持有innerBooleanQuery的构造参数类型是FullTextQuery[],因此你完全可以在布尔查询里嵌套BoostQuery或另一个BooleanQuery,构造出"(A 必须 且 B 应该)但不能 C"这类高精度检索表达式。

6. 小结

BooleanQuery是 LanceDB Node.js SDK 中构造复合全文检索的核心工具:

  • 构造函数接收[Occur, FullTextQuery][]数组,用MUST/SHOULD/MUST_NOT表达每个子查询的约束强度;
  • queryType()固定返回FullTextQueryType.Boolean,标识这是一个布尔组合查询;
  • 内部通过 napi 把Occur与子查询inner转发到 Rust 层(query.rs),由底层 FTS 引擎统一求值;
  • 实际使用时,将它传给Table.search(),配合createIndex建立的 FTS 索引即可执行"AND / OR / NOT"组合检索,仓库测试 table.test.ts 提供了可直接对照验证的完整用例。

对需要精确控制命中条件与排除规则的全文检索场景(如搜索包含某关键词但排除另一关键词的文档),BooleanQuery是比普通字符串搜索更可靠、语义更明确的方案。

【免费下载链接】lancedbDeveloper-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.项目地址: https://gitcode.com/gh_mirrors/la/lancedb

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

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

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

立即咨询