findOne
查找符合条件的第一个实体,未找到返回 null。
方法签名
findOne(options: FindOneOptions<T>): Observable<InstanceType<T> | null>
参数
interface FindOneOptions<T> {
where: RuleGroup<InstanceType<T>>;
orderBy?: OrderBy[];
}
示例
根据条件查找
import { firstValueFrom } from 'rxjs';
const todo = await firstValueFrom(
Todo.findOne({
where: {
combinator: 'and',
rules: [{ field: 'id', operator: '=', value: '591e97aa-f7e3-499c-9fa4-4e2ae4459ef6' }]
}
})
);
if (todo) {
console.log(todo.title);
}
查找最新记录
const latest = await firstValueFrom(
Todo.findOne({
where: { combinator: 'and', rules: [] },
orderBy: [{ field: 'createdAt', sort: 'desc' }]
})
);
复杂条件
const userTodo = await firstValueFrom(
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' }
]
})
);
组合复杂条件
const urgentTodo = await firstValueFrom(
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()
}
]
}
]
}
})
);
在组件中使用
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 {
@Input() todoId!: string;
todo$!: Observable<Todo | null>;
ngOnInit() {
this.todo$ = Todo.findOne({
where: {
combinator: 'and',
rules: [
{
field: 'id',
operator: '=',
value: this.todoId
}
]
}
});
}
}
findOne vs findOneOrFail
| 方法 | 未找到时行为 | 返回类型 | 使用场景 |
|---|---|---|---|
findOne | 返回 null | Observable<T | null> | 允许结果为空的查询 |
findOneOrFail | 抛出错误 | Observable<T> | 期望必定存在的查询 |
// findOne - 处理可能不存在的情况
const todo = await firstValueFrom(Todo.findOne({ where: { ... } }));
if (todo) {
// 处理找到的情况
} else {
// 处理未找到的情况
}
// findOneOrFail - 不存在时抛出错误
try {
const todo = await firstValueFrom(Todo.findOneOrFail({ where: { ... } }));
// 确定 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 firstValueFrom(
Todo.findOne({
where: {
combinator: 'and',
rules: [{ field: 'title', operator: '=', value: '重复的标题' }]
}
}).pipe(map(todo => !!todo))
);
获取默认值
const todo = await firstValueFrom(
Todo.findOne({
where: {
combinator: 'and',
rules: [{ field: 'id', operator: '=', value: todoId }]
}
}).pipe(map(todo => todo ?? createDefaultTodo()))
);
参考
- findOneOrFail - 查找单个实体,找不到抛出错误
- get - 根据 ID 直接获取实体
- find - 查询多个实体
- 查询操作符 - 查询条件操作符详解