Skip to content

IndexedDB - 读取数据

存储数据只是故事的一半;你需要高效地检索数据。IndexedDB 提供了多种数据读取方法,从获取单个记录到迭代数百万条目。为了获得最佳性能,所有读取操作都应在 readonly 事务中进行。

以下是你将使用的主要方法,以简洁的 idb 库语法显示:

  • db.get(storeName, key):通过主键从 storeName 中检索单个对象。如果未找到匹配对象,则返回 undefined。
  • db.getAll(storeName, [query], [count]):从 storeName 中检索所有对象。可选地,你可以提供一个键范围 query 来过滤结果。非常方便,但对于大型数据集要谨慎使用,因为它会将所有内容加载到内存中。
  • index.get(key):从索引中检索与 key 匹配的第一个对象。
  • index.getAll(key):从索引中检索与 key 匹配的所有对象。
  • store.openCursor([query]):最强大且内存效率最高的方法。游标允许你逐个迭代记录,这对于处理大型数据集而无需一次性将其全部加载到内存中至关重要。

此示例设置了一个员工数据库,并在他们的 department 上创建了索引。然后演示了每种核心读取方法来解决不同的查询。

<!DOCTYPE html>
<html lang="en">
<head>
<title>IndexedDB 读取数据</title>
<script type="module" src="app.js"></script>
</head>
<body>
<h1>从 IndexedDB 读取数据</h1>
<p>请检查控制台输出。</p>
</body>
</html>
// app.js
import { openDB } from 'https://cdn.jsdelivr.net/npm/idb@7/build/esm/index.js';
const DB_NAME = 'CompanyDB';
const STORE_NAME = 'employees';
const DEPT_INDEX = 'department_idx';
async function setupAndQuery() {
const db = await openDB(DB_NAME, 1, {
upgrade(db) {
const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });
store.createIndex(DEPT_INDEX, 'department', { unique: false });
},
});
// 使用事务清除现有数据并添加新数据
const tx = db.transaction(STORE_NAME, 'readwrite');
await tx.store.clear(); // 清空存储区以进行干净的演示运行
await Promise.all([
tx.store.add({ name: 'Alice', department: 'Engineering' }),
tx.store.add({ name: 'Bob', department: 'Marketing' }),
tx.store.add({ name: 'Charlie', department: 'Engineering' }),
tx.store.add({ name: 'Diana', department: 'HR' }),
]);
await tx.done;
console.log('数据库已填充。');
console.log('\n--- 查询示例 ---');
// 1. 按主键(例如,ID 2)获取单个员工
const bob = await db.get(STORE_NAME, 2);
console.log('1. 按主键(ID 2)获取:', bob);
// 2. 获取所有员工
const allEmployees = await db.getAll(STORE_NAME);
console.log('2. 获取所有员工:', allEmployees);
// 3. 使用索引获取“工程”部门的所有员工
const engineers = await db.getAllFromIndex(STORE_NAME, DEPT_INDEX, 'Engineering');
console.log('3. 通过索引获取(department = Engineering):', engineers);
// 4. 使用游标迭代并仅记录营销部门的员工
console.log('4. 正在使用游标查找营销人员:');
let cursorTx = db.transaction(STORE_NAME, 'readonly');
let store = cursorTx.objectStore(STORE_NAME);
for await (const cursor of store.iterate()) {
if (cursor.value.department === 'Marketing') {
console.log(` - 找到: ${cursor.value.name}`);
}
}
db.close();
}
setupAndQuery();

如果 get() 或 getAll() 操作在你期望有数据时返回 undefined 或空数组,请检查以下内容:

  • 正确的键/值: 你确定你正在查询的键或索引值确实存在吗?仔细检查拼写错误和大小写敏感性。
  • 事务范围: 在启动事务时是否包含了正确的对象存储区名称?
  • 异步时序: 确保你在尝试使用读取操作的结果之前 await 它。