HTML5 Advanced Series: indexedDB Database

Keywords: Javascript Database Attribute html5 less

Preface

In the local storage of HTML5, there is a kind of database called indexedDB, which is a kind of NoSQL database stored locally on the client side. It can store a large amount of data. From the first part: HTML5 Advanced Series: web Storage We know that web Storage can easily and flexibly access simple data locally, but the advantages of indexedDB are more obvious for large amounts of structured storage. Next, let's look at how indexedDB stores data.

Connect to the database

A website can have multiple indexedDB databases, but the name of each database is unique. We need to connect to a specific database by the name of the database.

var request = indexedDB.open('dbName', 1);  // Open dbName database
request.onerror = function(e){              // Listen for execution when connection database fails
    console.log('Failure to connect database');
}
request.onsuccess = function(e){            // Listen for execution when the connection database is successful
    console.log('Successful connection to database');
}

We use the indexedDB.open method to connect to the database. This method receives two parameters, the first is the database name, and the second is the database version number. This method returns an IDBOpenDBRequest object, representing a request object that requests a connection to the database. By listening for onsuccess and onerror events of the requesting object, we can define the method to be executed for connection success or failure.

Because the data warehouse in the database is not allowed to change in the same version in the indexedDB API, it is necessary to pass in a new version number in the indexedDB.open method to update the version so as to avoid duplicating the modification of the database in the same version. Version number must be integer!

var request = indexedDB.open('dbName', 2);  // Update version, open version 2 Database
// ...
request.onupgradeneeded = function(e){
    console.log('The new database version number is=' + e.newVersion);
}

We define the method to be executed when the database version is updated by listening for onupgradeneeded events of the request object.

close database

An IDBOpenDBRequest object is returned when the database is successfully connected using indexedDB.open. We can call the close method of the object to close the database.

var request = indexedDB.open('dbName', 2);
// ...
request.onsuccess = function(e){
    console.log('Successful connection to database');
    var db = e.target.result;
    db.close();
    console.log('The database is closed');
}

Delete the database


indexedDB.deleteDatabase('dbName');
console.log('The database has been deleted');

Creating Object Warehouse

object store (object warehouse) is the basis of indexedDB database. There are no database tables in indexedDB, while object warehouse is equivalent to a database table.

var request = indexedDB.open('dbName', 3);
// ...
request.onupgradeneeded = function(e){
    var db = e.target.result;
    var store = db.createObjectStore('Users', {keyPath: 'userId', autoIncrement: false});
    console.log('Creating Object Warehouse Successfully');
}

The db.createObjectStore method receives two parameters, the first is the object warehouse name, the second is an optional parameter, and the value is a js object. The keyPath attribute in this object is the primary key, which is equivalent to the id as the primary key in the database table. If the autoIncrement attribute is false, it means that the primary key value does not increase by itself. When adding data, the primary key value should be specified.

Note: In the database, the object warehouse name cannot be repeated, otherwise the browser will report an error.

Create an index

In indexedDB database, an index is created by an attribute of the data object. When searching in the database, it can only be retrieved by an attribute set as an index.

var request = indexedDB.open('dbName', 4);
// ...
request.onupgradeneeded = function(e){
    var db = e.target.result;
    var store = db.createObjectStore('newUsers', {keyPath: 'userId', autoIncrement: false});
    var idx = store.createIndex('usernameIndex','userName',{unique: false})
    console.log('Index Creation Successful');
}

The store.createIndex method receives three parameters, the first is the index name, the second is the attribute of the data object. In the example above, the user Name attribute is used to create the index, and the third parameter is an optional parameter with a value of a js object. The unique attribute in the object is true, which means that the index value cannot be the same, that is, the userName of the two data can not be the same, and that of false can be the same.

Transaction-based

In indexedDB, all data operations can only be performed in transactions. Once the connection to the database is successful, you can use the transaction method of the IDBOpenDBRequest object to open a read-only transaction or a read-write transaction.

var request = indexedDB.open('dbName', 5);
// ...
request.onupgradeneeded = function(e){
    var db = e.target.result;
    var tx = db.transaction('Users','readonly');
    tx.oncomplete = function(e){
        console.log('The transaction is over');
    }
    tx.onabort = function(e){
        console.log('The transaction was aborted');
    }
}

The db.transaction method receives two parameters. The first parameter can be a string or an array. The first parameter can be an object warehouse name when a string is used, and the second is an array composed of object warehouse names. Transaction can operate on any object warehouse in the parameters. The second parameter is transaction mode, which can only read the object warehouse, but not write when it is passed into readonly. readwrite can be passed in for reading and writing operations.

Operational data

  • add(): Add data. Receive a parameter for the object that needs to be stored in the object warehouse.

  • put(): add or modify data. Receive a parameter for the object that needs to be stored in the object warehouse.

  • get(): Get data. Receive a parameter for the primary key value of the data to be retrieved.

  • delete(): Delete data. Receive a parameter for the primary key value of the data to be retrieved.

var request = indexedDB.open('dbName', 5);
// ...
request.onsuccess = function(e){
    var db = e.target.result;
    var tx = db.transaction('Users','readwrite');
    var store = tx.objectStore('Users');
    var value = {
        'userId': 1,
        'userName': 'linxin',
        'age': 24
    }
    var req1 = store.put(value);        // Save data
    var req2 = store.get(1);            // Get data with index userId of 1
    req2.onsuccess = function(){
        console.log(this.result.userName);    // linxin
    }
    var req3 = store.delete(1);             // Delete data with index 1
    req3.onsuccess = function(){
        console.log('Successful deletion of data');        // Successful deletion of data
    }
}

The difference between add and put is that when put saves data, if the primary key of the data already has the same primary key in the database, it modifies the object corresponding to the primary key in the database, and uses add to save data. If the primary key already exists, the save fails.

Retrieval of data

We know above that we can get data using get(), but we need to set the primary key value. If we want to get data from an interval, we can use a cursor. The cursor is created and opened by the openCursor method of the object warehouse.

The openCursor method receives two parameters. The first one is the IDBKeyRange object, which is created by the following methods:

// boundRange represents a collection of primary key values from 1 to 10 (including 1 and 10).
// If the third parameter is true, it means that the minimum key value 1 is not included, and if the fourth parameter is true, it means that the maximum key value 10 is not included and the default is false.
var boundRange = IDBKeyRange.bound(1, 10, false, false);

// onlyRange represents a set of primary key values. The only() parameter is the primary key value and the integer type.
var onlyRange = IDBKeyRange.only(1);

// lowerRaneg represents a set of primary key values greater than or equal to 1.
// The second parameter is optional, true means no minimum primary key 1, false includes, default false
var lowerRange = IDBKeyRange.lowerBound(1, false);

// upperRange represents a set of primary key values less than or equal to 10.
// The second parameter is optional, true means no maximum primary key 10, false contains, default false
var upperRange = IDBKeyRange.upperBound(10, false);

The second parameter of the openCursor method represents the direction of the cursor's reading. There are mainly the following:

  • next: The data in the cursor is arranged in ascending order of the primary key value, and the data with the same primary key value is read

  • nextunique: The data in the cursor is arranged in ascending order of the primary key value, and the primary key value is equal, only the first data is read.

  • prev: The data in the cursor is arranged in descending order by the primary key value, and the data with the same primary key value is read

  • prevunique: The data in the cursor is arranged in descending order by the primary key value, and the primary key value is equal, only the first data is read

var request = indexedDB.open('dbName', 6);
// ...
request.onsuccess = function(e){
    var db = e.target.result;
    var tx = db.transaction('Users','readwrite');
    var store = tx.objectStore('Users');
    var range = IDBKeyRange.bound(1,10);
    var req = store.openCursor(range, 'next');
    req.onsuccess = function(){
        var cursor = this.result;
        if(cursor){
            console.log(cursor.value.userName);
            cursor.continue();
        }else{
            console.log('Search End');
        }
    }
}

When there is data that meets the retrieval criteria, the data can be updated by update method:

cursor.updata({
    userId : cursor.key,
    userName : 'Hello',
    age : 18
});

The data can be deleted by delete method:

cursor.delete();

You can continue to read the next data through the continue method, otherwise you will not continue to read after reading the first data:

cursor.continue();

summary

From connecting database, creating object warehouse and index, to operating and retrieving data, the complete process of indexedDB accessing and accessing data is completed. The following is a complete example to better understand the indexedDB database. Code address: indexedDB-demo

More articles: lin-xin/blog

Posted by nilansanjaya on Fri, 05 Jul 2019 11:25:55 -0700