findOneOrFail
查找符合条件的单个“实体”(entity);若未找到则抛出“错误”。适用于“期望必定存在”的场景。
方法签名
findOneOrFail(options: FindOneOrFailOptions<T>): Observable<InstanceType<T>>
参数(FindOneOrFailOptions):
interface FindOneOrFailOptions<T> {
// 查询条件(支持关系字段与嵌套 RuleGroup)
where: RuleGroup<InstanceType<T>>;
// 排序(可选)—— 当条件可能匹配多条时用于确定返回顺序
orderBy?: OrderBy[];
}
更多 Rule/RuleGroup 与操作符说明,见: 查询操作符。
使用示例
1) 通过主键或唯一键获取
import { firstValueFrom, switchMap } from 'rxjs';
const todo = await rxdb.pipe(
switchMap(() =>
Todo.findOneOrFail({
where: { combinator: 'and', rules: [{ field: 'id', operator: '=', value: todoId }] }
})
),
firstValueFrom
);
2) 结合排序确保稳定结果
// 某用户最早创建的一条 Todo
const firstTodo = await rxdb.pipe(
switchMap(() =>
Todo.findOneOrFail({
where: {
combinator: 'and',
rules: [{ field: 'owner.id', operator: '=', value: userId }]
},
orderBy: [{ field: 'createdAt', sort: 'asc' }]
})
),
firstValueFrom
);
错误处理(Error Handling)
- 未找到时,底层“适配器”(adapter)会抛错。
- 在 SQLite 适配器下,错误类型为
RxdbAdapterSqliteError('not found')。 - 其它适配器也会抛出语义等价的“未找到”错误。
- 在 SQLite 适配器下,错误类型为
Promise 风格:
try {
const todo = await rxdb.pipe(
switchMap(() =>
Todo.findOneOrFail({
where: { combinator: 'and', rules: [{ field: 'id', operator: '=', value: id }] }
})
),
firstValueFrom
);
// 使用 todo
} catch (e) {
// 未找到,按需提示或跳转
}
Observable 风格:
import { catchError, of } from 'rxjs';
Todo.findOneOrFail({ where: { combinator: 'and', rules: [{ field: 'id', operator: '=', value: id }] } })
.pipe(
catchError(err => {
// 未找到:返回空 UI 状态或导航
return of(null);
})
)
.subscribe(value => {
/* ... */
});
与 findOne 的区别
| 方法 | 未找到时行为 | 返回类型 |
|---|---|---|
findOne | 返回 undefined | Observable<T | undefined> |
findOneOrFail | 抛出错误 | Observable<T> |
选择建议:
- 已有唯一性保证且必须要有结果时,使用
findOneOrFail - 允许“无结果”作为业务分支时,使用
findOne
常见陷阱(Pitfalls)
- 条件不唯一:where 匹配多条记录但未加
orderBy,返回哪条不可控;建议增加稳定排序字段(如createdAt,id)。 - 关系字段深度过深:
user.orders.owner.id这类深层关系会产生多次 JOIN,影响性能;请合理限制关系深度并建立必要索引。 - null 判断:请使用
operator: '=' | '!='且value: null,底层会生成IS NULL/IS NOT NULL;不要用in: [null]。 - 错误处理遗漏:在 Observable 流中忘记
catchError会导致流中断;在 Promise 风格中请使用try/catch。 - 过度依赖
findOneOrFail:当“未找到”是正常业务分支时应使用findOne避免以异常做控制流。
最佳实践
- 确定唯一性:使用主键/唯一索引字段,或添加
orderBy提升稳定性 - 抛错即控制流:在需要快速失败的路径里更合适
- 关系字段适度使用:需要 JOIN 的查询,优先对参与字段建立索引