IDB基础使用与练习

IDB基础使用与练习 npm install idb import { openDB } from idb;对比Dexie.js 链式语法更像 ORMwhere ().and ()写联合条件更舒服idb只是薄封装API 贴近原生适合学习底层索引原理。下面先给idb版本配套books 表然后练习题。idb对原生 IndexedDB 的轻量封装API 简单体积小适合项目只需要基础 CRUD。Dexie功能更完整支持事务、索引、查询、批量操作、版本迁移等复杂业务更舒服公司实际开发里更常见的是 Dexie初始化数据库import { openDB } from idb; // 初始化DB只执行一次 const db await openDB(BookStore, 1, { upgrade(db) { // 创建仓库主键 bookId const store db.createObjectStore(books, { keyPath: bookId }); // 普通索引 store.createIndex(price_idx, price); // 复合索引 [category, price] store.createIndex(category_price_idx, [category, price]); } });基础增删改查// 新增add 主键冲突抛错 async function addBook(book) { return await db.add(books, book); } // 更新put 存在则更新不存在新增 async function updateBook(book) { return await db.put(books, book); } // 根据主键删除 async function delBook(bookId) { return await db.delete(books, bookId); } // 根据主键查询单条 async function getBookById(bookId) { return await db.get(books, bookId); } // 查询全部 async function getAllBooks() { return await db.getAll(books); }联合条件查询两种方案方案 1索引缩小范围 JS 内存过滤简单不用复合索引条件category 小说 price 50async function queryBooksByCategoryAndMaxPrice(category, maxPrice) { // 拿到category完全匹配的所有记录 const list await db.getAllFromIndex(books, category_price_idx, IDBKeyRange.bound([category, 0], [category, maxPrice])); return list; }方案 2复合索引精确匹配高性能条件category计算机 price39async function queryByCompound(category, price) { return await db.getAllFromIndex(books, category_price_idx, IDBKeyRange.only([category, price])); }方案 3游标遍历for await ofidb 支持异步迭代器适合复杂多条件索引无法覆盖内存过滤async function filterByCursor(minPrice, category) { const tx db.transaction(books); const index tx.store.index(price_idx); const range IDBKeyRange.lowerBound(minPrice); const result []; // idb支持异步游标循环 for await (const cursor of index.openCursor(range)) { const item cursor.value; if(item.category category) { result.push(item); } cursor.continue(); } return result; }练习题使用 idb 库表结构{ bookId: number, title: string, author: string, price: number, category: string }索引price_idx、复合索引category_price_idx: [category,price]全部用idbAPI不能写原生onupgradeneeded回调那套事件写法。题 1【新增】编写函数addBookSafe(book)调用db.add捕获主键冲突错误并返回提示。题 2【更新】编写updateBookPrice(bookId, newPrice)只更新书籍价格字段不覆盖其他字段。提示先 get 拿到旧对象修改 price 再 put。题 3【范围查询】编写getBooksBetweenPrice(min, max)利用price_idx查询价格区间min price max的书籍数组。题 4【复合索引联合查询】编写getBooksByCatAndPriceRange(category, minPrice, maxPrice)利用复合索引category_price_idx查询同一分类价格在区间内的书籍。题 5【游标 多条件过滤】编写searchByAuthorAndMinPrice(authorName, minPrice) 用 price_idx 拿到价格 minPrice 的数据游标遍历内存额外判断author authorName返回结果。题 6【综合题】编写searchBooks({category, minPrice, maxPrice})参数对象三个字段都可选如果传入 category优先使用复合索引缩小范围如果同时传 minPrice/maxPrice叠加价格区间都不传返回全部书籍找不到返回空数组。Dexie.js 版本DexieIndexedDB 的封装库链式 API多条件查询写起来很舒服复合索引声明简单。 安装npm install dexie1. 初始化数据库 表定义import Dexie from dexie; // 创建实例 const db new Dexie(BookStoreDexie); // 版本1定义仓库和索引 db.version(1).stores({ books: bookId, price, [categoryprice] // bookId主键 // price普通索引 // [categoryprice]复合索引 category price }); // 表结构 // { bookId: number, title: string, author: string, price: number, category: string } export default db;2. 基础增删改查import db from ./db; // 新增 async function addBook(book) { // bookId 重复会抛异常 return await db.books.add(book); } // 更新整行覆盖 async function updateBook(book) { return await db.books.put(book); } // 只局部更新某个字段推荐不会覆盖其他属性 async function updateBookPrice(bookId, newPrice) { return await db.books.update(bookId, { price: newPrice }); } // 删除 async function delBook(bookId) { return await db.books.delete(bookId); } // 根据主键查单条 async function getBookById(bookId) { return await db.books.get(bookId); } // 查询全部 async function getAllBooks() { return await db.books.toArray(); }3. 联合条件查询重点① 复合索引查询走索引性能好查询category计算机价格区间[20, 60]async function getBooksByCatAndPriceRange(category, minPrice, maxPrice) { return await db.books .where([categoryprice]) .between([category, minPrice], [category, maxPrice]) .toArray(); }② 索引缩小范围 .and () 内存过滤常用.where()的字段会走索引.and()里面的条件是拿到数据后 JS 内存过滤适合无法用索引表达的复杂条件// 条件price minPrice 并且 author authorName async function searchByAuthorAndMinPrice(authorName, minPrice) { return await db.books .where(price) .aboveOrEqual(minPrice) .and(item item.author authorName) .toArray(); }③ 综合多条件搜索category、minPrice、maxPrice 可选async function searchBooks({ category, minPrice, maxPrice }) { let query db.books; if (category) { query query.where([categoryprice]).between([category, minPrice ?? 0], [category, maxPrice ?? Infinity]); } else { if (minPrice ! undefined) query query.where(price).aboveOrEqual(minPrice); if (maxPrice ! undefined) query query.where(price).belowOrEqual(maxPrice); } return await query.toArray(); }配套练习题Dexie.js沿用上面books表结构索引price、复合索引[categoryprice]编写addBookSafe(book)新增书籍捕获主键冲突错误返回友好提示。编写函数根据bookId修改书籍title使用局部更新update()。编写getBooksBetweenPrice(min, max)利用 price 索引查询价格区间书籍。使用复合索引[categoryprice]写函数查询category小说且价格 10~40 的所有书籍。编写查询category 历史并且书名包含指定关键词提示关键词不能走索引需要.and 内存过滤。综合查询参数支持 category、minPrice、maxPrice、author全部可选动态拼接查询条件返回结果。Dexie 小考点.where()只能用已声明索引字段否则不走索引会全表扫描.and()内部是内存过滤适合复杂条件数据量大时慎用update()局部更新put()整行替换复合索引写法[ab]