Skip to content

IndexedDB - 范围

IndexedDB:使用 IDBKeyRange 查询数据范围

Section titled “IndexedDB:使用 IDBKeyRange 查询数据范围”

除了获取单个记录之外,你还需要查询特定范围内的数据。例如,查找今天收到的所有电子邮件,或价格在 50 美元到 100 美元之间的所有产品。IndexedDB 正为此目的提供了 IDBKeyRange 对象。

一个 IDBKeyRange 定义了键的一个连续范围。你可以将其与 getAll()、openCursor() 或 count() 等方法一起使用,以从对象存储或索引中过滤结果。

IDBKeyRange 对象有几个静态方法来定义不同类型的范围:

方法描述示例(范围)
IDBKeyRange.lowerBound(lower, [open])匹配所有大于或等于 lower 的键。如果 open 为 true,则匹配严格大于 lower 的键。≥ a or > a
IDBKeyRange.upperBound(upper, [open])匹配所有小于或等于 upper 的键。如果 open 为 true,则匹配严格小于 upper 的键。≤ b or < b
IDBKeyRange.bound(lower, upper, [lowerOpen], [upperOpen])匹配所有在 lower 和 upper 之间的键。open 标志可用于排除边界。≥ a && ≤ b
IDBKeyRange.only(value)只匹配精确等于 value 的键。= c

以下是如何将这些范围应用于具有 price 索引的 products 存储的一些示例。

// 查找价格 >= 100 的产品
const range1 = IDBKeyRange.lowerBound(100);
const expensiveProducts = await db.getAllFromIndex('products', 'priceIdx', range1);
// 查找价格 < 20 的产品(不包含 20)
const range2 = IDBKeyRange.upperBound(20, true);
const cheapProducts = await db.getAllFromIndex('products', 'priceIdx', range2);
// 查找价格在 50 到 150 之间的产品(包含 50 和 150)
const range3 = IDBKeyRange.bound(50, 150);
const midRangeProducts = await db.getAllFromIndex('products', 'priceIdx', range3);
// 查找所有价格精确为 99.99 的产品
const range4 = IDBKeyRange.only(99.99);
const specificPriceProducts = await db.getAllFromIndex('products', 'priceIdx', range4);

一个常见的用例是根据日期范围获取记录。此示例创建一个 logs 存储,添加带有时间戳的条目,然后查询在过去一小时内创建的日志。

<!DOCTYPE html>
<html lang="en">
<head>
<title>IndexedDB 范围查询示例</title>
</head>
<body>
<h1>检查控制台输出</h1>
<script type="module">
import { openDB } from 'https://cdn.jsdelivr.net/npm/idb@7/build/index.js';
async function runDemo() {
const db = await openDB('appLogsDB', 1, {
upgrade(db) {
const store = db.createObjectStore('logs', { autoIncrement: true });
store.createIndex('timestampIdx', 'timestamp');
},
});
const twoHoursAgo = new Date();
twoHoursAgo.setHours(twoHoursAgo.getHours() - 2);
const thirtyMinsAgo = new Date();
thirtyMinsAgo.setMinutes(thirtyMinsAgo.getMinutes() - 30);
// 添加一些示例数据
const tx = db.transaction('logs', 'readwrite');
await Promise.all([
tx.store.add({ message: 'User logged in', timestamp: new Date() }),
tx.store.add({ message: 'Data fetched from API', timestamp: thirtyMinsAgo }),
tx.store.add({ message: 'Old session cleared', timestamp: twoHoursAgo }),
]);
await tx.done;
// 查询过去一小时的日志
const oneHourAgo = new Date();
oneHourAgo.setHours(oneHourAgo.getHours() - 1);
const range = IDBKeyRange.lowerBound(oneHourAgo);
const recentLogs = await db.getAllFromIndex('logs', 'timestampIdx', range);
console.log('Logs from the last hour:');
console.table(recentLogs);
}
runDemo().catch(console.error);
</script>
</body>
</html>

控制台将显示一个表格,其中包含过去一小时内的两条日志条目(‘User logged in’ 和 ‘Data fetched from API’),不包括两小时前的条目。