跳转到正文

查询

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。