跳到主要内容

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);
});

最佳实践

  1. 评估数据量:使用前先评估可能的数据量
  2. 添加过滤条件:尽量通过 where 条件减少返回的数据量
  3. 考虑分页:数据量超过 1000 条时考虑使用 find 分页
  4. 缓存结果:对于不常变化的数据,考虑缓存查询结果
  5. 监控性能:在生产环境监控 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
}))
);
// 分批处理数据

参考