跳到主要内容

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')
    • 其它适配器也会抛出语义等价的“未找到”错误。

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返回 undefinedObservable<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 的查询,优先对参与字段建立索引

参考