indexeddb通过索引和游标支持范围查询,需先为非主键字段创建索引,再用idbkeyrange定义区间并调用opencursor或getall;复合索引遵循前缀匹配规则,范围查询须从左到右连续。

IndexedDB 支持通过 索引(Index) 和 游标(Cursor) 实现结构化数据的范围查询,核心是利用 IDBKeyRange 定义键的区间,并配合 openCursor() 或 getAll() 等方法执行查询。
创建带索引的对象存储,为范围查询打基础
要按非主键字段做范围查询(比如按时间、价格、状态等),必须先在对象存储中创建对应字段的索引。
// 打开数据库并创建/升级结构
const request = indexedDB.open('myApp', 2);
request.onupgradeneeded = function (event) {
const db = event.target.result;
const store = db.createObjectStore('orders', { keyPath: 'id' });
// 创建索引:按 status 字段(允许重复值)
store.createIndex('byStatus', 'status', { unique: false });
// 创建复合索引:按 createdAt + amount(适合时间+金额范围组合查询)
store.createIndex('byTimeAndAmount', ['createdAt', 'amount'], { unique: false });
};
用 IDBKeyRange 构造查询范围
IDBKeyRange 是定义键范围的关键工具,支持单点、左闭右开、左右闭合等多种区间形式:
-
IDBKeyRange.lowerBound(100):≥ 100 -
IDBKeyRange.upperBound(500):≤ 500 -
IDBKeyRange.bound(100, 500, true, true):> 100 且 -
IDBKeyRange.bound([new Date('2024-01-01'), 0], [new Date('2024-12-31'), Infinity]):复合索引范围(日期+金额)
在索引上执行范围查询
获取索引后,调用 index.openCursor(range) 或 index.getAll(range) 即可:
function queryOrdersByStatus(db, statusStart, statusEnd) {
return new Promise((resolve, reject) => {
const tx = db.transaction('orders', 'readonly');
const store = tx.objectStore('orders');
const index = store.index('byStatus');
const range = IDBKeyRange.bound(statusStart, statusEnd);
const cursorReq = index.openCursor(range);
const results = [];
cursorReq.onsuccess = function () {
const cursor = cursorReq.result;
if (cursor) {
results.push(cursor.value);
cursor.continue(); // 继续遍历下一条
} else {
resolve(results);
}
};
cursorReq.onerror = () => reject(cursorReq.error);
});
}
// 使用示例:查 status 在 'pending' 到 'shipped' 之间的订单
queryOrdersByStatus(db, 'pending', 'shipped').then(console.log);
处理复合索引的多维范围查询
对于按多个字段联合排序的查询(如「2024 年内金额 100–1000 的订单」),需注意复合索引的“前缀匹配”规则:
- 索引字段顺序很重要:定义为
['date', 'amount'],则只能高效查询date === X AND amount ∈ [a,b]或date ∈ [d1,d2](不带 amount 条件) - 不能跳过前导字段:无法只对
amount做范围查询,除非单独建 amount 索引 - 范围需从左到右连续:支持
date = '2024-06-01' AND amount ∈ [200,800],也支持date ∈ ['2024-01-01','2024-12-31'],但不支持date ∈ [...] AND amount = 500配合模糊 date —— 此时应换用游标遍历 + JS 过滤
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











