查询
RecordQuery 是与 stream() 配合使用的流式筛选器。它涵盖追加式访问模式:从游标处继续读取、读取时间窗口、按字段相等条件筛选,以及在达到限制时停止。对于更丰富的谓词、排序和基于索引的查找,请使用查询构建器;对于普通 foreach 在数据流上可执行的所有操作,RecordQuery 是开销更低的工具。
RecordQuery 是不可变的。每个修饰方法都会返回一个克隆的查询:
PHP
$query = Storh\RecordQuery::all()
->after($lastSeenId)
->time_range_ms($fromMs, $untilMs)
->where_equal('kind', 'page')
->limit(100);
foreach ($store->stream($query) as $record) {
// Records are yielded lazily.
}
after() 和 time_range_ms() 使用 UUID 排序,因此记录数据中无需包含时间戳字段。在 SegmentedLog 上,它们还会跳过无关工作:ID 范围超出窗口的分段不会被打开;每段的稀疏索引会直接定位到接近首条匹配记录的位置,无需从头扫描。
where_equal() 会将顶层数据字段与 === 进行比较,并接受标量值或 null。null 筛选器会匹配字段存在且值为 null 的记录;不含该字段的记录不会匹配。
游标分页
ID 按创建时间排序,因此一页的最后一个 ID 就是下一页的游标:
PHP
$page = iterator_to_array($store->stream(
Storh\RecordQuery::all()->after($lastSeenId)->limit(100)
), false);
$lastSeenId = [] === $page ? $lastSeenId : end($page)->id();
跳过损坏记录
默认情况下,扫描会在遇到第一条无法读取的记录时抛出错误。如果扫描应跳过该记录并报告错误,请使用
continue_on_error():
PHP
$query = Storh\RecordQuery::all()->continue_on_error(
static function (string $location, Throwable $error): void {
error_log($location . ': ' . $error->getMessage());
},
);
对于 DocStore,位置是记录 ID;对于 SegmentedLog,位置为 segment-file:byte-offset。repair() 才是实际清理损坏记录的工具;参见CLI。