indexedDB中创建和使用索引
前言
关于indexedDB的基础知识,可以查阅 Indexed Database API (W3C) s Using_IndexedDB (MDN) 和 使用IndexedDB (中文).
关于indexedDB的索引,我仔细翻看了W3C API才弄明白是怎么回事,在上面另外2个链接的教程中,都没有介绍索引的使用。
索引,就是以数据的快速查询为目的。
本文展示如何在indexedDB中创建和使用索引来优化数据查询。网上搜索到的indexedDB入门教程中,都没有介绍索引的使用,或是只带过了一下怎么创建索引,没提可以用来干什么。我在这里给出一个简洁完整的例子,示范一下indexedDB索引的使用。
索引需求场景示例
假设现在有一组如下的数据:
id 姓 姓名
1 张 张三
2 张 张四
3 张 张五
4 张 张六
5 王 王五
6 王 王六
其中包含4个姓张,2个姓王。
如何快速方便的查询出所有姓张的记录呢?
针对需求示例使用索引
如果不用索引,代码上就要查询出全部记录,然后对每个记录进行判断过滤。
如果用索引,就能直接按指定参数查处某姓的全部记录。
创建索引的代码片段示例:
store.createIndex("ix_familyName", "familyName", {unique: false});
插入测试数据的代码片段示例:
store.put({familyName: "张", name: "张三"}); store.put({familyName: "张", name: "张四"}); store.put({familyName: "张", name: "张五"}); store.put({familyName: "张", name: "张六"}); store.put({familyName: "王", name: "王五"}); store.put({familyName: "王", name: "王六"});
查询所有姓张的记录的代码片段示例:
var keyRange = IDBKeyRange.only("张"); var req = store.index("ix_familyName").openCursor(keyRange);
这样得到的结果中,将不会包含其他姓的记录。
使用索引的完整demo代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>IndexedDB's index usage demo</title> </head> <body> <h1>indexedDB中索引的使用demo</h1> <pre> 姓:<input type="text" id="tx1" value="张">名:<input type="text" id="tx2"><button id="btnAdd">add</button> result: <textarea id="taResult" rows="10" cols="90"></textarea> <button id="btnRead">read</button> <button id="btnDelDB">deleteDatabase</button> </pre> <script> function $$(id){return document.getElementById(id);} var dbName = 'testDB1', storeName = 'testStore1', dbVersion = 1; $$('btnAdd').onclick = add; $$('btnRead').onclick = read; $$('btnDelDB').onclick = function (){ indexedDB.deleteDatabase(dbName); }; function read(){ openDB(function (db){ var transaction = db.transaction(storeName,"readonly"); transaction.oncomplete = function(event) { console.log("transaction oncomplete"); }; var store = transaction.objectStore(storeName); //使用索引查询所有姓张的记录 var keyRange = IDBKeyRange.only("张"); var req = store.index("ix_familyName").openCursor(keyRange, "next"); var records = []; $$('taResult').value = ''; req.onsuccess = function(event) { var cursor = event.target.result; if (!cursor) { //打印查询结果集 $$('taResult').value = records.join('\n'); return; } records.push(cursor.primaryKey + ' ' + cursor.key + ' ' + cursor.value.familyName + ' ' + cursor.value.name); cursor.continue(); }; }); } function add(){ openDB(function (db){ var transaction = db.transaction(storeName,"readwrite"); transaction.oncomplete = read; var store = transaction.objectStore(storeName); var req = store.put({familyName: $$('tx1').value, name: $$('tx2').value}); req.onsuccess = function(event) { read(); }; }); } function openDB(callback){ if(openDB.db){ callback(openDB.db); return; } var openRequest = indexedDB.open(dbName, dbVersion); openRequest.onupgradeneeded = function (e) { console.log('openRequest.onupgradeneeded'); var db = e.target.result; if(!db.objectStoreNames.contains(storeName)) { var store = db.createObjectStore(storeName, {keyPath:"id", autoIncrement: true}); //创建索引 store.createIndex("ix_familyName", "familyName", {unique: false}); //插入初始化测试数据 store.put({familyName: "张", name: "张三"}); store.put({familyName: "张", name: "张四"}); store.put({familyName: "张", name: "张五"}); store.put({familyName: "张", name: "张六"}); store.put({familyName: "王", name: "王五"}); store.put({familyName: "王", name: "王六"}); } }; openRequest.onsuccess = function(e) { console.log('openRequest.onsuccess'); if(callback){ openDB.db = e.target.result; callback(e.target.result); } }; } </script> </body> </html>