findOne
查找符合条件的第一个实体,如果未找到则返回 undefined。
方法签名
findOne(options: FindOneOptions<T>): Observable<InstanceType<T> | undefined>
参数说明
interface FindOneOptions<T> {
// 查询条件
where: RuleGroup<InstanceType<T>>;
// 排序条件(可选)
orderBy?: OrderBy[];
}
使用场景
1. 根据条件查找单个实体
import { firstValueFrom, switchMap } from 'rxjs';
// 查找特定 ID 的 todo
const todo = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{
field: 'id',
operator: '=',
value: '591e97aa-f7e3-499c-9fa4-4e2ae4459ef6'
}
]
}
})),
firstValueFrom
);
if (todo) {
console.log('找到 todo:', todo.title);
} else {
console.log('未找到 todo');
}
2. 查找最新创建的记录
const latestTodo = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
})),
firstValueFrom
);
3. 查找特定用户的第一个待办事项
const userFirstTodo = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{
field: 'userId',
operator: '=',
value: 'user-123'
},
{
field: 'completed',
operator: '=',
value: false
}
]
},
orderBy: [
{ field: 'priority', sort: 'desc' },
{ field: 'createdAt', sort: 'asc' }
]
})),
firstValueFrom
);
4. 使用复杂条件查询
const urgentIncompleteTodo = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{
field: 'completed',
operator: '=',
value: false
},
{
combinator: 'or',
rules: [
{
field: 'priority',
operator: '=',
value: 'high'
},
{
field: 'dueDate',
operator: '<',
value: new Date()
}
]
}
]
}
})),
firstValueFrom
);
5. 在组件中使用
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-todo-detail',
template: `
<div *ngIf="todo$ | async as todo; else notFound">
<h2>{{ todo.title }}</h2>
<p>{{ todo.description }}</p>
</div>
<ng-template #notFound>
<p>未找到待办事项</p>
</ng-template>
`
})
export class TodoDetailComponent implements OnInit {
todo$!: Observable<Todo | undefined>;
ngOnInit() {
this.todo$ = rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{
field: 'id',
operator: '=',
value: this.todoId
}
]
}
}))
);
}
}
findOne vs findOneOrFail
| 方法 | 未找到时行为 | 返回类型 | 使用场景 |
|---|---|---|---|
findOne | 返回 undefined | Observable<T | undefined> | 允许结果为空的查询 |
findOneOrFail | 抛出错误 | Observable<T> | 期望必定存在的查询 |
// findOne - 处理可能不存在的情况
const todo = await rxdb.pipe(
switchMap(() => Todo.findOne({ where: { ... } })),
firstValueFrom
);
if (todo) {
// 处理找到的情况
} else {
// 处理未找到的情况
}
// findOneOrFail - 不存在时抛出错误
try {
const todo = await rxdb.pipe(
switchMap(() => Todo.findOneOrFail({ where: { ... } })),
firstValueFrom
);
// 确定 todo 存在
} catch (error) {
// 处理错误
}
性能优化建议
1. 使用索引字段查询
// ✅ 好:使用主键或索引字段
Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'id', operator: '=', value: 'xxx' }
]
}
});
// ⚠️ 慢:使用非索引字段
Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'description', operator: 'contains', value: 'keyword' }
]
}
});
2. 添加合适的 orderBy
如果查询结果可能有多条,添加 orderBy 可以确保返回一致的结果:
Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'userId', operator: '=', value: 'user-123' }
]
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
});
常见用例
检查记录是否存在
const exists = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'title', operator: '=', value: '重复的标题' }
]
}
})),
map(todo => !!todo),
firstValueFrom
);
获取默认值
const todo = await rxdb.pipe(
switchMap(() => Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'id', operator: '=', value: todoId }
]
}
})),
map(todo => todo ?? createDefaultTodo()),
firstValueFrom
);
参考
- findOneOrFail - 查找单个实体,找不到抛出错误
- get - 根据 ID 直接获取实体
- find - 查询多个实体
- 查询操作符 - 查询条件操作符详解