Loading JSON File into IndexedDB

Script showing how to populate an IDB from a file and access content.

The IndexedDB database consists of a list of value keys. So, identifiers associated with objects that form useful content: data or scripts...

In fact, keys can be part of contained objects, as happens in our example when you store JavaScript objects that can come from JSON files exported from another database. You can also store scripts.

Example data file:

{ "fruits": [
  {
	"name": "orange",	
	"color":"orange",
	"origin":"Asia",
	"content":"200"
  },
  {
	"name": "apple",  
	"color":"red, green, yellow",
	"origin":"Asia",
	"content":"1000"
  },
  {
	"name":"strawberry",   
	"color": "red",
	"origin": "France",
	"content":"50"
  },
  {
	"name":"blueberry",
	"color":"purple",
	"origin":"America",
	"content":"300"
  }
 ]
}

1) Download JSON file

async function loadJSON(fname) {
  var response = await fetch(fname)
  var str = await response.text()
  var data = JSON.parse(str)
  var idb = await importIDB("fruits", "fstore", data["fruits"])
  await displayIDB(idb, "fstore", "storage")
}

The JSON file is loaded as text and converted to an object using JSON.parse ().

The function is declared asynchronous so that await can be used and therefore wait for the download to complete in order to associate it with the content display.

2) Transfer its contents to the database

function importIDB(dname, sname, arr) {
  return new Promise(function(resolve) {
    var r = window.indexedDB.open(dname)
    r.onupgradeneeded = function() {
      var idb = r.result
      var store = idb.createObjectStore(sname, {keyPath: "name"})
    }
    r.onsuccess = function() {
      var idb = r.result
        let tactn = idb.transaction(sname, "readwrite")
    	  var store = tactn.objectStore(sname)
        for(var obj of arr) {
          store.put(obj)
        }
        resolve(idb)
    }
    r.onerror = function (e) {
     alert("Enable to access IndexedDB, " + e.target.errorCode)
    }    
  })
}

The importIDB parameter contains the name of the database, the name of the table (store), and a table listing the objects to be placed in the table .

The database is opened by the open indexedDB method. The table is created using the createObjectStore method in the function associated with the onupgradened event.

The keyPath: "name" parameter is used to set the lookup key to the "name" property, which is part of each object stored in the database. This is equal to the primary key column in SQL.

When the database is successfully created, the success event is fired and the contents of the associated function are executed. The transaction then opens to access the table and store the records.

3) Show the contents of the database

The following function has only a demonstration purpose to ensure that the fill is done correctly. The application assumes that the database contains thousands of records, so its contents are not displayed in the block.

However, it is useful to see how you can use the cursor to view the contents of the database, whether you want to search there and, possibly, use queries like GraphQL.

function displayIDB(idb, sname, id) {
  let storage = document.getElementById(id)
  let tactn = idb.transaction(sname, "readonly")
  let osc = tactn.objectStore(sname).openCursor()
  osc.onsuccess = function(e) {
    let cursor = e.target.result
    if (cursor) {
      storage.innerHTML += "Name " + cursor.value["name"] + " : " + cursor.value["origin"] + " " + cursor.value["color"] + "<br>"
      cursor.continue()
    }
  } 
  tactn.oncomplete = function() {
    idb.close();
  }
}

You need to open a transaction to access the table of records, and the feature of indexedDB is to use the "cursor" to parse the content.
When the operation is complete, the oncelete complete event is fired and the base is closed (this is an option).

4) Record access

async function getIDB(dname, sname, key) {
  return new Promise(function(resolve) {
    var r = indexedDB.open(dname)
      r.onsuccess = function(e) {
        var idb = r.result
        let tactn = idb.transaction(sname, "readonly")
        let store = tactn.objectStore(sname)
        let data = store.get(key)
        data.onsuccess = function() {
          resolve(data.result)
        }
        tactn.oncomplete = function() {
          idb.close()
        }
     }
  })
}

The base is reopened because it was closed in a previous function. A new transaction is executed, and the store.get () method finds the record to which the key is given.

This function returns the promised so that you can verify that the content is available before viewing. This depends on the feature enabled when the button is pressed, which is the following feature in our demo:

async function search() {
  var key = document.getElementById("searchval").value
  var infos = await getIDB("fruits", "fstore", key)
  document.getElementById("storage").innerHTML = JSON.stringify(infos, null, ' ')
}

An alternative is to use callback.

The full code is available in the archive for download.

To run the demo, load demoIDB.html into Firefox or another browser that accepts file downloads from a local page.

See also: