Pocketbase查询
概述
@emresandikci/pocketbase-query 是一个小的,零依赖的TypeScript查询生成器 PocketBase过滤器. 它通过流畅的、可链接的API构建过滤器字符串,安全地转义值,并删除值为空的条件,这使得可选过滤器(搜索表单、表过滤器)保持简单。
它遵循PocketBase v0.40过滤器语法。
安装
npm i @emresandikci/pocketbase-query
// ESM / TypeScript
import PocketbaseQuery from '@emresandikci/pocketbase-query';
// CommonJS
const PocketbaseQuery = require('@emresandikci/pocketbase-query').default;
使用
getInstance<T>() 返回一个新的查询生成器。 T 是您的记录类型,并为您提供对字段名称的自动完成和类型检查。每个调用都返回自己的实例,因此查询可以并行构建或嵌套构建。
import PocketBase from 'pocketbase';
import PocketbaseQuery from '@emresandikci/pocketbase-query';
interface Post {
title: string;
status: string;
comments: number;
tags: string[];
created: string;
}
const pb = new PocketBase('http://127.0.0.1:8090');
const filter = PocketbaseQuery.getInstance<Post>()
.equal('status', 'active')
.and()
.greaterThan('comments', 50)
.build();
// status="active" && comments>50
const posts = await pb.collection('posts').getFullList({
filter,
expand: 'comments_via_post',
});
可选的过滤器
具有空值的条件(null, undefined, '', NaN)和 && / || 在它们周围留下空括号。你可以链接所有可能的过滤器,并让构建器丢弃未使用的过滤器:
function buildFilter(form: { search?: string; status?: string; tag?: string }) {
return PocketbaseQuery.getInstance<Post>()
.openBracket()
.like('title', form.search)
.or()
.anyLike('tags', form.tag)
.closeBracket()
.and()
.equal('status', form.status)
.build();
}
buildFilter({ search: 'pocketbase' }); // (title~"pocketbase")
buildFilter({ status: 'active' }); // status="active"
buildFilter({}); // ""
字段和值
字段
field 是…的钥匙 T,可选:
- 一个修饰词:
title:lower(不区分大小写),tags:length(项数),tags:each(每项) - 关系路径:
author.name
query.like('title:lower', 'news').and().greaterThan('tags:length', 2).and().equal('author.name', 'John');
// title:lower~"news" && tags:length>2 && author.name="John"
值
value 可以 string | number | boolean | Date | null | undefined.
| 价值 | 输出 |
|---|---|
'active' | "active"逃脱了 pb.filter() 在官方SDK中,所以用户输入中的引号和反斜杠不能脱离字符串 |
50, true | 50, true (无报价) |
new Date('2026-01-02T03:04:05Z') | "2026-01-02 03:04:05.000Z" (PocketBase日期时间格式) |
'@now', '@todayStart',…… | @now, @todayStart (日期时间宏,不带引号) |
null, undefined, '', NaN | 跳过条件 |
支持宏: @now, @second, @minute, @hour, @weekday, @day, @month, @year, @yesterday, @tomorrow, @todayStart, @todayEnd, @monthStart, @monthEnd, @yearStart, @yearEnd.
编辑器在键入值时建议使用这些宏,在键入字段时建议使用带有修饰符的字段名。任何其他字符串仍然作为正常值工作。
query.greaterThanOrEqual('created', '@todayStart').and().lessThan('created', new Date('2026-12-31'));
// created>=@todayStart && created<"2026-12-31 00:00:00.000Z"
API
比较的方法
所有的方法 (field, value) 并返回建造者进行链锁。
| 方法 | 运营商 | 方法(数组字段的任何项) | 运营商 |
|---|---|---|---|
equal | = | anyEqual | ?= |
notEqual | != | anyNotEqual | ?!= |
greaterThan | > | anyGreaterThan | ?> |
greaterThanOrEqual | >= | anyGreaterThanOrEqual | ?>= |
lessThan | < | anyLessThan | ?< |
lessThanOrEqual | <= | anyLessThanOrEqual | ?<= |
like | ~ | anyLike | ?~ |
notLike | !~ | anyNotLike | ?!~ |
like / notLike 匹配部分:PocketBase将值封装在 % 除非你加上 % 通配符('Lorem%')。
query.anyEqual('tags', 'sale');
// tags?="sale"
in(field, values)
加入一个 like 每个值的条件 ||. 空值将被跳过。
query.in('status', ['draft', 'review']);
// status~"draft" || status~"review"
因为它使用 ~, 'act' 同时匹配 active 和 inactive。使用 equal 与 or() 精确匹配。
customFilter(filter)
为构建器未涵盖的语法追加一个原始筛选器字符串,例如 strftime(), geoDistance(), @request.* 或者 @collection.*. 它是 不逃,所以永远不要传递不可信的输入。
query
.customFilter("strftime('%Y-%m', created) = '2026-01'")
.and()
.customFilter('geoDistance(address.lon, address.lat, 23.32, 42.69) < 25');
分组和逻辑
| 方法 | 增加了 |
|---|---|
and() | && |
or() | || |
openBracket() / closeBracket() | ( / ) |
query
.openBracket()
.equal('status', 'active')
.or()
.equal('status', 'pending')
.closeBracket()
.and()
.greaterThan('comments', 50)
.build();
// (status="active" || status="pending") && comments>50
输出
| 方法 | 返回 |
|---|---|
build() | 最后一个过滤器字符串。移除剩余的操作符和空括号,然后重置构造器。 |
getQuery() | 迄今为止构建的原始字符串,没有清除或重置。用于调试。 |
getLastQueryValue() | 添加到查询中的最后一个值。 |
开发
npm ci
npm test # jest
npm run typecheck # tsc
npm run validate # prettier --check + eslint
npm run build # tsup -> dist/ (ESM + CJS + types)
释放
版本和npm发布是自动使用的 semantic-release. 每一次推到 main 运行测试,并且自最后一个标记之后的提交包含 fix:, feat: 或者突破性的变化,下一个版本发布到NPM,并带有出处、标记和添加 CHANGELOG.md. 拉取请求会得到一个关于其将要发布的版本的注释。
提交与 npm run commit 或写 传统的提交 用手。
许可证
MIT许可证