用途
Live Queries 是 TanStack DB 中用于构建响应式派生集合的查询技能,构建在 db-core 之上。它使用类似 SQL 的链式查询构建器,创建出的派生集合会在底层数据发生变化时自动更新。查询引擎会把查询编译为增量视图维护(IVM)管道,借助差分数据流(d2ts)只重新计算增量部分,因此所有操作符、字符串函数、数学函数和聚合函数都以增量方式维护。官方建议优先使用这些查询操作符,而不是等价的 JavaScript 代码。
主要能力
过滤:通过链式 .where()(多个条件为 AND 关系)配合表达式操作符实现过滤,可使用 and()、or()、not()、inArray()、like() 等组合复杂逻辑,也可直接引用布尔列。比较遵循 PostgreSQL 语义:涉及 null 或 undefined 的比较结果未知、不匹配,需用 isNull() 或 isUndefined();NaN(以及无效 Date)等于自身并排在其他所有非空值之后。
连接:支持 join、leftJoin、rightJoin、innerJoin、fullJoin,默认连接类型为 left。连接条件接受 eq() 或由等值组成的非空(可嵌套)and(),仅支持等值连接(IVM 约束)。可链式进行多表连接。用于按需数据源时,第一个等值条件决定候选加载和索引选择,建议把选择性强的普通字段等值条件放在前面。
聚合:使用 groupBy 分组后在 select 中聚合,用 having 过滤分组;$selected 命名空间可用于在 having 和 orderBy 中引用 select 中定义的字段。若不使用 groupBy,select 中的聚合把整个集合视为一个分组。
派生集合复用:派生集合本身也是集合,可作为另一个查询的数据源以缓存中间结果。官方建议在模块作用域创建一次并复用,不要每次渲染或导航时重建。
虚拟属性:查询结果每行都会自动附带只读虚拟属性:$hasPendingWrites(存在影响该行的本地乐观写入时为 true,仅表示本地变更状态)、$origin(最后一次确认的变更来自本客户端则为 "local",否则 "remote")、$key(结果行键)、$collectionId(来源集合 ID)。这些属性可用于 where、select 和 orderBy,但不应持久化回存储。$synced 为已弃用别名,将在 1.0 RC 移除。
Includes 子查询:可在 select() 中嵌入相关子查询以生成嵌套数据。子查询必须包含一个用 eq() 将父字段与子字段关联的 where 子句,库会自动提取为连接条件。形式包括:集合 include(默认,每行返回一个子 Collection);toArray() 数组 include(返回普通数组,支持标量和对象 select);materialize() 普通值(父行保存普通快照,多行子查询返回 Array,findOne() 子查询返回 T | undefined,子结果变化时父行重新发出);concat(toArray()) 拼接标量为单个字符串。materialize() 与 toArray() 一样必须是 select 的顶层值,不能嵌套在 coalesce()、eq() 等表达式中。Includes 子查询与父查询编译进同一个增量管道,并非独立的 live query。
一次性查询 queryOnce:用于非响应式的一次性快照,创建 live query 集合、预加载、提取结果并自动清理。配合 findOne() 时解析为 T | undefined。适用于脚本、加载器、数据导出、测试或 AI/LLM 上下文构建;UI 绑定和响应式更新应使用 live query。
响应式副作用 createEffect:无需物化完整结果集即可响应查询结果变化,当行进入、离开或更新时触发回调,类似任意 live query 上的数据库触发器。关键选项包括 id(可选)、query、skipInitial、onEnter、onUpdate、onExit、onBatch、onError、onSourceError。ctx.signal 在 effect 被销毁时中止。
使用方式
最小示例(核心 API,无框架 hooks):可从 @tanstack/db 导入 createCollection、createLiveQueryCollection、liveQueryCollectionOptions、eq。方式一:使用 createLiveQueryCollection 简写;方式二:通过 liveQueryCollectionOptions 传入完整选项。结果是 live 集合,可迭代、订阅或作为数据源。详细代码示例见各操作章节。
重要行为与限制
- live query 集合默认 gcTime 为 5_000;显式 gcTime: 0 会被保留并禁用该派生集合的垃圾回收(注意这与 TanStack Query 中 gcTime: 0 的行为相反)。
- 无订阅者时启动同步有至少 50ms 的 GC 宽限期;挂起的 preload() 调用会保留集合直到其完成。
- 使用
===代替eq()会抛出 InvalidWhereExpressionError(JS === 返回布尔原始值而非表达式对象)。 - 在 JS 中做
.filter()/.map()会丢弃增量维护,每次变化都从头重跑。 .distinct()必须配合.select(),否则抛出 DistinctRequiresSelectError。.having()必须配合.groupBy(),否则抛出 HavingRequiresGroupByError。- 数学表达式可用于 orderBy();与 limit() 搭配使用时跳过懒加载优化,所有匹配行先全部加载再排序。字面值(如 Date.now())在查询创建时捕获,需要更新时须重建查询。
- 在标准 .select() 回调中,JS 的
||或三元表达式不能构建查询表达式,应使用coalesce()做空值回退、caseWhen()做条件计算字段。 fn.select()仅在确实需要任意 JavaScript 时使用,它无法像基于表达式的 .select() 那样被优化。
适用场景
- 在 UI 中展示查询结果(live query 集合 + useLiveQuery)。
- 响应变化执行副作用(createEffect 配合 onEnter / onUpdate / onExit)。
- 检视完整批次变更(createEffect 配合 onBatch)。
- 一次性快照:脚本、加载器、数据导出、测试、AI/LLM 上下文构建(queryOnce)。
暂未提供
关于定价、平台支持范围、性能基准等具体信息,资料暂未提供。