跳到主要内容

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返回 nullObservable<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()))
);

参考