findAll
查询所有符合条件的实体,不进行分页限制。适用于小数据集或需要完整数据的场景。
方法签名
findAll(options: FindAllOptions<T>): Observable<InstanceType<T>[]>
参数说明
interface FindAllOptions<T> {
// 查询条件
where: RuleGroup<InstanceType<T>>;
// 排序条件(可选)
orderBy?: OrderBy[];
}
使用场景
1. 获取所有数据
import { firstValueFrom, switchMap } from 'rxjs';
// 获取所有待办事项
const allTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
console.log(`共有 ${allTodos.length} 个待办事项`);
2. 带排序的查询
// 获取所有待办事项,按创建时间降序排列
const sortedTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
})),
firstValueFrom
);
3. 带过滤条件的查询
// 获取所有已完成的待办事项
const completedTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: [
{
field: 'completed',
operator: '=',
value: true
}
]
},
orderBy: [
{ field: 'completedAt', sort: 'desc' }
]
})),
firstValueFrom
);
4. 获取特定用户的所有数据
// 获取某个用户的所有待办事项
const userTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: [
{
field: 'userId',
operator: '=',
value: 'user-123'
}
]
},
orderBy: [
{ field: 'priority', sort: 'desc' },
{ field: 'createdAt', sort: 'asc' }
]
})),
firstValueFrom
);
5. 复杂条件查询
// 获取所有高优先级或紧急的未完成任务
const urgentTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: [
{
field: 'completed',
operator: '=',
value: false
},
{
combinator: 'or',
rules: [
{
field: 'priority',
operator: '=',
value: 'high'
},
{
field: 'tags',
operator: 'contains',
value: '紧急'
}
]
}
]
},
orderBy: [
{ field: 'dueDate', sort: 'asc' }
]
})),
firstValueFrom
);
6. 在组件中使用
Angular
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-todo-overview',
template: `
<div *ngIf="todos$ | async as todos">
<h2>所有待办事项 ({{ todos.length }})</h2>
<div *ngFor="let todo of todos">
<h3>{{ todo.title }}</h3>
<p>{{ todo.description }}</p>
</div>
</div>
`
})
export class TodoOverviewComponent implements OnInit {
todos$!: Observable<Todo[]>;
ngOnInit() {
this.todos$ = rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
}))
);
}
}
React
import { useEffect, useState } from 'react';
import { switchMap } from 'rxjs';
function TodoOverview() {
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
const subscription = rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
}))
).subscribe(setTodos);
return () => subscription.unsubscribe();
}, []);
return (
<div>
<h2>所有待办事项 ({todos.length})</h2>
{todos.map(todo => (
<div key={todo.id}>
<h3>{todo.title}</h3>
<p>{todo.description}</p>
</div>
))}
</div>
);
}
Vue
<template>
<div>
<h2>所有待办事项 ({{ todos.length }})</h2>
<div v-for="todo in todos" :key="todo.id">
<h3>{{ todo.title }}</h3>
<p>{{ todo.description }}</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { switchMap } from 'rxjs';
import { Subscription } from 'rxjs';
const todos = ref<Todo[]>([]);
let subscription: Subscription;
onMounted(() => {
subscription = rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'desc' }
]
}))
).subscribe(value => {
todos.value = value;
});
});
onUnmounted(() => {
subscription?.unsubscribe();
});
</script>
findAll vs find
| 方法 | 分页 | 性能 | 适用场景 |
|---|---|---|---|
findAll | 无分页 | 小数据集快,大数据集慢 | 需要全部数据,数据量小 |
find | 支持分页 | 稳定 | 大数据集,需要分页 |
// findAll - 获取所有数据
const allTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
// find - 分页获取
const someTodos = await rxdb.pipe(
switchMap(() => Todo.find({
where: {
combinator: 'and',
rules: []
},
limit: 100,
offset: 0
})),
firstValueFrom
);
性能注意事项
1. 数据量控制
findAll 会返回所有符合条件的数据,数据量大时可能导致性能问题:
// ⚠️ 警告:如果有 10000 条数据,全部加载会很慢
const allTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
// ✅ 更好:添加过滤条件,减少数据量
const recentTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: [
{
field: 'createdAt',
operator: '>=',
value: new Date(Date.now() - 30 * 86400000) // 最近30天
}
]
}
})),
firstValueFrom
);
// ✅ 或者使用分页
const pagedTodos = await rxdb.pipe(
switchMap(() => Todo.find({
where: {
combinator: 'and',
rules: []
},
limit: 100
})),
firstValueFrom
);
2. 何时使用 findAll
适合使用 findAll 的场景:
- 数据量小(< 1000 条)
- 需要在内存中处理全部数据
- 下拉选择框选项
- 配置数据、元数据
- 导出功能
不适合使用 findAll 的场景:
- 数据量大(> 1000 条)
- 用户列表、订单列表等大数据集
- 需要分页展示的列表
- 实时更新的大数据流
常见用例
1. 下拉选择框数据
// 获取所有分类,用于下拉选择框
const categories = await rxdb.pipe(
switchMap(() => Category.findAll({
where: {
combinator: 'and',
rules: [
{
field: 'active',
operator: '=',
value: true
}
]
},
orderBy: [
{ field: 'name', sort: 'asc' }
]
})),
firstValueFrom
);
2. 统计分析
// 获取所有数据进行统计分析
const allTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
// 统计各状态的数量
const stats = {
total: allTodos.length,
completed: allTodos.filter(t => t.completed).length,
pending: allTodos.filter(t => !t.completed).length,
highPriority: allTodos.filter(t => t.priority === 'high').length
};
3. 数据导出
// 导出所有待办事项为 CSV
async function exportTodos() {
const todos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
},
orderBy: [
{ field: 'createdAt', sort: 'asc' }
]
})),
firstValueFrom
);
const csv = [
['ID', '标题', '描述', '状态', '创建时间'],
...todos.map(t => [
t.id,
t.title,
t.description,
t.completed ? '已完成' : '未完成',
t.createdAt.toISOString()
])
];
return csv;
}
4. 数据迁移
// 批量更新所有数据
async function migrateAllTodos() {
const todos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
for (const todo of todos) {
// 执行数据迁移逻辑
await Todo.update(todo, {
// 更新字段
});
}
}
5. 本地搜索和过滤
// 获取所有数据,然后在内存中进行复杂过滤
const allTodos = await rxdb.pipe(
switchMap(() => Todo.findAll({
where: {
combinator: 'and',
rules: []
}
})),
firstValueFrom
);
// 自定义复杂过滤逻辑
const filtered = allTodos.filter(todo => {
// 复杂的 JavaScript 过滤逻辑
return customFilterLogic(todo);
});
最佳实践
- 评估数据量:使用前先评估可能的数据量
- 添加过滤条件:尽量通过 where 条件减少返回的数据量
- 考虑分页:数据量超过 1000 条时考虑使用
find分页 - 缓存结果:对于不常变化的数据,考虑缓存查询结果
- 监控性能:在生产环境监控
findAll的性能表现
替代方案
当数据量大时,考虑以下替代方案:
// 方案 1: 使用 find 分页
const pagedData = await rxdb.pipe(
switchMap(() => Todo.find({
where: { combinator: 'and', rules: [] },
limit: 100,
offset: 0
})),
firstValueFrom
);
// 方案 2: 使用 findByCursor 游标分页
const cursorData = await rxdb.pipe(
switchMap(() => Todo.findByCursor({
where: { combinator: 'and', rules: [] },
orderBy: [
{ field: 'createdAt', sort: 'desc' },
{ field: 'id', sort: 'asc' }
],
limit: 100
})),
firstValueFrom
);
// 方案 3: 使用流式处理(如果支持)
const stream$ = rxdb.pipe(
switchMap(() => Todo.find({
where: { combinator: 'and', rules: [] },
limit: 100
}))
);
// 分批处理数据
参考
- find - 支持分页的查询
- findByCursor - 基于游标的分页查询
- count - 统计数量
- 查询操作符 - 查询条件操作符详解