IndexedDB - 搜索
IndexedDB:搜索和查询数据
Section titled “IndexedDB:搜索和查询数据”作为一种结构化数据库,IndexedDB 提供了高效的数据搜索和检索机制。你可以根据主键查询记录,或者使用索引对对象的其他属性进行更复杂的查找。
检索数据最直接的方式是使用 get() 方法通过主键进行。对于更高级的查询,你可以使用 IDBKeyRange 对象来指定键的范围。
基于键的搜索主要方法有:
store.get(key):搜索与键匹配的第一个值。store.getAll([query], [count]):搜索与可选查询(键或键范围)匹配的所有值,最多count个。store.getKey(key):搜索与键匹配的第一个键。store.getAllKeys([query], [count]):搜索与可选查询匹配的所有键,最多count个。store.count([query]):获取与可选查询匹配的记录总数。
示例:按键和范围查询
Section titled “示例:按键和范围查询”// 假设 'db' 是一个来自 'idb' 库的已打开的 IDBDatabase 实例
// 通过 ID(主键)获取单个产品const product = await db.get('products', 'prod-123');
// 获取 ID 在 'prod-100' 和 'prod-200' 之间的所有产品const keyRange = IDBKeyRange.bound('prod-100', 'prod-200');const products = await db.getAll('products', keyRange);
// 只获取前 5 个产品键const keys = await db.getAllKeys('products', null, 5);使用索引搜索
Section titled “使用索引搜索”要高效地按主键以外的属性进行搜索,你必须创建一个索引。索引根据指定属性维护一个指向对象的排序引用列表,从而实现快速查找。
索引只能在 openDB 的 upgrade 回调中创建。
语法:objectStore.createIndex()
Section titled “语法:objectStore.createIndex()”objectStore.createIndex(indexName, keyPath, [options]);indexName:索引的唯一名称。keyPath:要索引的对象的属性路径(例如'price'或'address.city')。options:一个可选对象,包含配置属性:
unique: true:确保存储中没有两条记录可以拥有相同的索引键值。尝试添加重复项将导致错误。
multiEntry: true:如果 keyPath 解析为数组,则索引将为数组的每个成员添加一个条目。这非常适合实现标签或类别功能。
示例:创建索引
Section titled “示例:创建索引”// 在 'upgrade' 回调中const productsStore = db.createObjectStore('products', { keyPath: 'id' });
// 创建一个索引,用于按产品 'category' 搜索产品productsStore.createIndex('categoryIdx', 'category', { unique: false });
// 使用 multiEntry 为标签创建索引productsStore.createIndex('tagsIdx', 'tags', { multiEntry: true });完整搜索示例
Section titled “完整搜索示例”此示例演示如何设置一个包含 ‘products’ 存储和 ‘category’ 索引的数据库,添加数据,然后搜索 ‘electronics’ 类别中的所有产品。
<!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('shopDB', 1, { upgrade(db) { if (!db.objectStoreNames.contains('products')) { const store = db.createObjectStore('products', { keyPath: 'id' }); store.createIndex('categoryIdx', 'category'); } }, });
const tx = db.transaction('products', 'readwrite'); const store = tx.objectStore('products');
// 添加一些示例数据 await Promise.all([ store.put({ id: 'p1', name: 'Laptop', category: 'electronics' }), store.put({ id: 'p2', name: 'T-Shirt', category: 'apparel' }), store.put({ id: 'p3', name: 'Keyboard', category: 'electronics' }), ]);
await tx.done; console.log('Database populated!');
// 现在,使用索引搜索所有 'electronics' 产品 const electronics = await db.getAllFromIndex('products', 'categoryIdx', 'electronics');
console.log('Electronics Products:', electronics); console.table(electronics); }
runDemo().catch(console.error); </script></body></html>预期输出(在浏览器控制台中)
Section titled “预期输出(在浏览器控制台中)”Database populated!Electronics Products: [ { id: 'p1', name: 'Laptop', category: 'electronics' }, { id: 'p3', name: 'Keyboard', category: 'electronics' } ]
(console.table output)┌─────────┬──────┬───────────┬───────────────┐│ (index) │ id │ name │ category │├─────────┼──────┼───────────┼───────────────┤│ 0 │ 'p1' │ 'Laptop' │ 'electronics' ││ 1 │ 'p3' │ 'Keyboard'│ 'electronics' │└─────────┴──────┴───────────┴───────────────┘