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代碼

[可運行的完整的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>


發佈了165 篇原創文章 · 獲贊 151 · 訪問量 148萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章