-
- a front end NoSQL database
- an alternative to the WebSQL Database, deprecated by 2010-11-18
- WebSQL Database:
- a relational database access system
- useful for storing pairs of keys and their corresponding values
- IndexedDB:
- an indexed table system
- providing in-order retrieval of keys, efficient searching of values, and the storage of duplicate values for a key
- WebSQL Database:
- requirement: user agents (apps running in browsers) probably requiring to store a large numbers of objects locally to satisfy off-line data query of Web applications
- databases
- Object Stores
- w/ a name and attached to a "domain"
- sharing features of full SQL databases (transactions, indexes, ...) and of
LocalStorage
(key-value pairs) - values: fill JavaScript objects
- indexing system based on object properties for faster retrieval and search
- example:
{firstName: 'Michel', lastName: 'Buffa'}
- designed to work w/ huge amount of data
- asynchronous (callbacks for each operation): CALLBACKS EVERYWHERE!
- WC3 spec. providing a concrete API to perform advanced key-value data management
- data management at the heart of most sophisticated query processors
- using transactional databases to store keys and their corresponding values (one or more per key)
- providing a means of traversing keys in a deterministic order
- often implemented through the use of B-tree data structures
- B-tree: considered efficient for inertion and deletion, as well as for in-order traversal of vary large numbers of data records
- sample applications:
- Google Drive
- Guitar pedalbord
- examples form from the courses
- PS4/XBox One/Windows desktop or car dashboard
-
- IndexedDB: a transactional Object Store where able to store JavaScript objects
- indexes on same properties of these objects facilitate faster retrieval and search
- applications using IndexedDB able to work both online and offline
- IndexedDB transactional: managing concurrent access to data
-
- store and retrive objects indexed by a key
- transaction: changes to the databases
- same-origin policy: only accessing data within the same domain, not able to access across domains
- extensive use of an asynchronous API: most processing done in callback functions
-
- each origin w/ an associated set of database
- a database comprises one or more object stores
- name of a database
- used to identify a databas within a specific origin
- any string value, including the empty string
- remaining constant for the lifetime of the database
- version of a database
- current version as a property of the database
- version 0: default value when a database created
- only one version at any given time
- connection
- created as a database open
- multiple connects existed for a given database at any given time
-
- mainly based on Chrome but other browsers w/ equivalent means for debugging
- executing app to create an IndexedDB w/ name = "customers"
- calling
createDB()
function to create a database- creating a new IndexedDB database and an object store in it
- inserting two JS objects
- checking w/ devtools > Application > IndexedDB to show the IndexedDB database, object store and data
- syntax to create database:
var request = indexedDB.open(dbName, verNo);
- no
verNo
$\to$ entering theonupgradeneeded
callback where the database actually is created -
verNo
existed$\to$ callingrequest.onsuccess
callback to add/remove/search data
- no
-
onupgradeneeded
callback- triggered on a create database request
- always in a default transaction
- unable to overlap w/ another transaction at the same time
- best practice: declare a variable to store the database
$\gets$ the DOM event result attribute = the database
-
Example: creating database
-
- syntax:
indexedDB.deleteDatabase("dbName");
- common practice for learner: execute the command in devtools > console
- syntax:
- Object store
- the mechanism by which data is stored in the database
- name of object store
- must have property
- unique within the database to which it belongs
- records (JavaScript objects)
- key-value pairs persistently held
- one of these keys as a kind of "primary key" in the SQL database sense
- key: a property that every object in the datastore must contain
- values: structured but probably varied btw objects
- example: person contacts in database, email as "the key all objects must define", some may have first name and last name. others may have an address or no address at all
- stored according to keys, in ascending order, within an object store
- probably having a key generator and a key path
- in-line keys: datastore w/ a key path
- out-of-line keys: datastore w/o a key path
- able to derive the key from
- key generator: a monotonically increasing number every time a key needed, similar to auto-incremented primary keys in a SQL database
- a key path
- explicitly specified when a value is stored in the object stores
- Version
- version 0: a database first created
- one version ar a time
- no multiple versions existed at once
- changing the version by opening it w/ a higher version number tha the current one
- syntax: starting a
versionchange
transaction and triggering anupgradeneeded
event - the handler of the event: only place to update the schema of the database
IDBDatabase.setVersion()
method deprecated
-
- a data value by which stored values are organized and retrieved in the object store
- key derived from one of the sources
- a key generator
- a key path
- explicitly specified value
- key w/ a data type having a number greater than the one before
- each record in an object store must have a unique key within the same store
- types of key
- string
- date
- array: ranging from an empty in an object store using an index
-
- a mechanism for producing new key in an ordered sequence
- an object store w/o a key generator
$\to$ application must provide keys for records being stored - similar to auto-generated primary keys in SQL databases
-
- a key stored as part of of the stored
- found using a key path
- probably generated using a generator
- stored in the value using the key path or used as a key once generated
- example: the email of a person or a student number in an object representing a student in a student store
-
- a key stored separately from the value being stored
- an auto-incremental
id
not part of the key
-
- a must-have property defined by object stores
- equivalent to Primary key in relational database
- unique
- able to be explicit (ssn) or implicit (auto-incremented primary key in SQL)
- implicit KeyPath: not appeared in the stored objects themselves
- stored objects w/o a rigidly defined schema
- only key to be shared, other keys probably varying btw stored objects
- example:
{firstName: 'Michel', lastName: 'Buffa', ssn: "1122334455"}
$\to$ ssn as Keypath
-
- where the browser should extract the key from a value in the object store or index
- valid key path including one of
- an empty string
- a JavaScript identifier
- multiple JavaScript identifiers separated by period w/o spaces
- Value
- each record w/ a value
- anything abel to be expressed in JavaScript, including, boolean, number, string, date, object, array, regexp, undefined and null
- object/array: the properties and values in it able to be anything but valid
- blog and files supported by all major browsers, IE > 9
-
- stored object able to have one or more indexes
$\to$ faster searching - a common concept in database
- unique or non-unique
- making lookup possible using any arbitrary property of the store objects
- speeding up object retrieval and allowing multi-criteria searches
- possible to have non unique indexes
$\to$ all matching objects - example: "lastName" property of each person as an index
$\to$ make search faster for some persons by "lastName"
- stored object able to have one or more indexes
-
- IndexedDB storing key-value pairs
- values: complex objects (think of JSON objects)
- keys: properties of the objects
- creating indexes w/ any property of the objects for faster searching and ordering results
- example:
- declare key-value pairs:
const customerData = [{ ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" }, { ssn: "555-55-5555", name: "Donna", age: 32, email="donna@home.org" }];
-
customerData
: an array of "customers" - customer properties:
ssn
for social security number, aname
, anage
and anemail
address
- declare key-value pairs:
-
- sometimes useful to retrieve records from an object store through their means than their keys
- allowing the user to look up records in an object store by using the properties of the values in the object store's records
- able to speed up object retrieval and allow multi-criteria
- a specialized persistent key-value storage
- having a referenced object store
- reference store probably w/ an index store associated w/ it
- a list of records holding the data stored in the index
- records in an index automatically populated whenever records in the referenced object store are inserted, updated or deleted
- several indexes referencing the same object store
$\to$ changes to the object store causing all such indexes to update
- containing a unique flag set to
true
- no two records in the index w/ the same key
- failed if attempt to insert or modify a record in the index's referenced object store
- sometimes useful to retrieve records from an object store through their means than their keys
-
- transactional database: ensuring concurrent access to data not compromised
- using "locking system" to prevent compromising
- scenarios to lock system
- multiple tabs opened on the same WebApp (same domain)
- multiple apps running "out of traditional browser" (game console, windows desktop, etc.)
-
IndexedDB and transaltion model
- IndexedDB built on a transactional database model
- operations in IndexedDB
$\to$ operated in the context of a transaction - IndexedDB API providing lots of objects representing indexes, tables, cursors, etc.
- API tied to a particular transaction
- unable to execute commands or open cursors outside a transaction
- transaction committed automatically, unable to committ manually
- useful when considering what might happen if a user opened two of the web apps in two different tabs simultaneously
-
Typical syntax of a transaction
- open a transaction for reading and writing on the DB "customer":
var transaction = db.transaction("customers", "readwrite");
- add complete listener:
transaction.oncomplete = function(evt) { alert("All done!"); };
- add error listener:
transaction.onerror = function(evt) { // error handling };
- access data:
var objectStore = transaction.objectStore("costomers");
- iterate through to add data:
for (var i in customerData) {...}
- add data:
var request = objectStore.add(customerData[i]);
- add success listener:
request.onsuccess = function(evt) { // evt.target.result === customerData[i].ssn };
- add data:
- open a transaction for reading and writing on the DB "customer":
-
- an atomic and durable set of data-access and data-modification operation
- used to interact w/ the data in a database
- data read and written to the database done by using a transaction
- mode:
- type:
read
,readwrite
, orversionchange
- determining which types of interaction performed upon that transaction
- set when transaction created and remain fixed for the life of the transaction
- type:
- a transaction in IndexedDB similar to a transaction in a SQL database
- all succeed or all fail within all operations of a transaction
- connection
- transaction created through a connection
- allowing multiple active transaltions associated w/ a connection at a time
- scope
- defined at creation time
- determining the object stores w/ which the transaction may interact
- determining which concurrent transactions can read or write the same data
- write transactions unable to have overlapping scope. i.e., working on the same data at the same time
- multiple reads allowed at the same time while writes in sequence, only one at a time overlapped
- a
versionchange
transaction- never runs concurrently w/ other transactions
- automatically created when a database w/ higher version number is provided
- transaction activated inside the
onupgradeneeded
event handler, allowing the creation of new object stores and indexes
-
readwrite
transactions w/ overlapped scopes always run in the order they were created and never run in parallel
- example:
- existing a writing transaction in a database connection
- scope of the transaction covering only the
flyingMonkey
object store - starting a second transaction w/ a scope of the
unicornCentaur
andunicornPegasus
object stores - allowing several reading transactions and probably overlapped
-
- all operations in the database happened within a transaction
- implicit transactions during the creation of the database
- explicit transactions for adding/removing/updating/retrieving data
- generating a transaction object from the database:
- indicating which object store associated
- specifying and access mode
- syntax:
var transaction = db.transaction(["objStoreName", ...], mode);
-
mode
: eitherreadonly
,readwrite
, orversionchange
-
versionchange
: only for creating a new database or for modifying its schemas -
readonly
: concurrent read transactions allowed
-
- Scope
- the set of object stores and indexes to which a transaction applies
- read-only transactions: able to overlap and execute at the same time
- writing transaction:
- unable to overlap
- multiple transactions w/ same scope at the same time allowed but queue up and execute in sequence
- Request
- issued as the reading and writing on a database done
- represeting one read or one write operation
- always run within a transaction
- example: add a customer to the object store named "customers"
- access data
- iterate through to add data
-
IndexedDB API and asynchronous
- most IndexedDB API asynchronous
- API not providing returned data but passed a callback function
- not "store" a value or "retrieve" a value out of the database but "request" that a database operation happens
- database system notifying caller via a DOM event once operation done
- the type of event specifying the success or failure of the operation
- examples:
transaction.oncomplete
,transaction.onsuccess
,request.onerror
, etc.
-
- requests:
- objects receiving the success or failure DOM events
onsuccess
andonerror
properties
- using
addEventListener()
andremoveEventListener()
to add and remove listeners - status of a request:
readyState
,result
, anderrorCode
- meaning of
result
depending on how the request was generated, e.g.,IDBCursor
instance or the key for a value
- requests:
-
- IndexedDB using DOM events to notify browser when results available
- properties of event
type
: always presented, possible valuessuccess
orerror
target
: showing where the event is headed
IDBRequest
object:- the most common value of the
target
of an event - generated as a result of doing some database operation
- the most common value of the
- success events: neither bubbled up nor cancelled
- error events:
- both bubbled and able to be cancelled
- abort the transaction, unless cancelled
- IndexedDB and object-oriented
- IndexedDB:
- object-oriented, not a relational database
- a Object Store
- creating an object store for a type of data
- simply persist JavaScript objects to that store
- object store w/ a collection of indexes to enable efficient querying and iteration
- indexes: corresponding to the properties of the JavaScript object stored in the store
- relational database:
- tables w/ rows and columns
- having a table to store a collection of rows and columns of named types of data
- using SQL for query
- fundamental difference to affect the way to design and build applications
- IndexedDB:
-
Same-origin policy
- a origin consists of the domain, the application layer protocol, and the port of a URL of the document
- script exected within the document
- IndexedDB adheres to a same-origin policy
- each origin associated to its own set of databases
- every database having a name to identify itself within the origin
- concept of "same origin": the combination of all three components, domain, protocol, and port
- example:
- an app in page w/ the URL,
https://www.example.com/app/
- a second app at
https://www.example.com/dir
- booth apps accessing the same IndexedDB batabase
$\gets$ the same origin,https
,example.com
, and80
- apps at
https://www.example.com:8080/dir
(different port) orhttp://www.example.com/dir/
(different protocol)$\to$ not the same origin
- an app in page w/ the URL,
-
- a mechanism for iterating over multiple records within a key range
- existing a source defining which index or object store it is iterating
- having a position within the range
- retrieving records sequentially according to the value of their keys in descending or ascending way
-
- a continuous interval over some data type used for keys
- retrieving records via object stores and indexes using keys or a range of keys
- able to limit and filter the range using lower and upper bounds
- example: iterate over all values of a key btw x and y
-
Typical procedure to inset data
- create a transaction
- map the transaction onto the object store
- create an "add" request that will take part in the transaction
-
Example: basic steps
- tasks
- get a transaction on the "customer" object store in
readwrite
mode - init transaction on the ObjectStore
- get request from the transaction for adding a new object
- get a transaction on the "customer" object store in
- tasks
-
Example: adding data to DB from a form
- process
- press the "Create database" button first
- add a new customer using the form
- click the "add a new Customer" button
- use devtools to inspect the IndexedDB store contents (refresh or close/open the devtools probably required)
- good practice: checking the database open before interting an element
- validation for inserting data and alerting w/ error message
-
ssn
existed: the property declared as the keyPath (kind of primary key) in the object store schema and unique -
email
address existed: the property declared as an index and unique - same customer inserted twice or duplicated SSN
$\to$ customized alert message
-
- process
-
Example: removing data
- procedure
- click "create database button" to ensure the open of the existing database
- use devtools to check the customer w/
ssn=444-44-4444
, if not existed, add the customer from the input forms - refresh IndexedDB in devtools to observe the customer
- click the "Remove the customer" button and observe the data object in devtools after refreshing
- procedure
-
Example: modifying data
-
Typical syntax for adding/deleting/modifying/retrieving data
- assign request:
var request = objectStore.get(keyPath);
- assign index:
var index = onjectStore.index(key);
- add new object:
request.add(object);
- remove a existing object:
request.delete(keypath);
- modify data from an object store w/ IndexedDB:
request.put(keypath);
- retrieve/search object w/ keyPath:
request.get(keyPath);
- search object w/ index:
index.get(key);
- assign request:
-
Example: retrieving/searching data w/ key
-
Example: retrieving/searching data w/ key - short version
- only one object store
$\to$ not required to passing a list of object stores in transaction - read only: no need for "readwrite" transaction but default "readonly`
- no request object required
- only one object store
-
Searching for multiple objects
- getting all of the data from the datastore using a
cursor
-
cursor
- a special object traversing the object storage, given a query, and returning one key/value at a time, thus saving memory
- walking through the store in key order (ascending by default) as an object store stored internally by key
- syntax:
let request = store.openCursor(query, [direction]);
-
query
: a key or key range, same as forgetAll
-
direction
(optional):-
"next"
: the default, the cursor walks up from the record w/ the lowest key -
"prev"
: the reverse order, down from the record w/ the biggest key -
"nextunique"
,"prevunique"
: same as above, but skip records w/ the same key
-
-
-
get()
requiring which key to retrieve - using a
cursor
object to step through all the values or a certain range in object - searching data via keyPath
- the
onsuccess
callback for cursor and letvar cursor = evt.target.result;
- the
cursor
object = the result property of the request - the actual key and value able to be found on the key and value properties of the cursor object
- call
cursor.continue()
to get the next object if required - reach end of the the data
$\to$ get asuccess
callback but w/result
property undefined
- the
- getting all of the data from the datastore using a
-
Example: retriving/searching more data
-
Example: retrieving/searching more data and storing in array
-
Example: getting data using an index
- tasks:
- create an
index
object corresponding to the "name" property -
get
method on the index-object to retrieve the person's object from the object store
- create an
- tasks:
-
- normal cursor: mapping the index property to the object in the object store
- key cursor: mapping the index property to the key used to store the object in the object store
-
- add cursor success handler:
index.openCursor().onsuccess = function(evt) {...}
- get cursor:
var cursor = evt.target.result;
- check cursor existence:
if (cursor) { alert("Name: " + cursor.key + ", SSN: " + cursor.value.ssn + ", email: " + cursor.value.email); cursor.continue(); }
- add cursor success handler:
-
- add key cursor success handler:
index.openKeyCursor().onsuccess = function(evt) {...}
- get cursor:
var cursor = evt.target.result;
- check cursor existence:
if (cursor) { alert("Name: " + cursor.key + ", SSN: " + cursor.value); cursor.continue(); }
- add key cursor success handler:
-
Example: searching w/ index
-
- MDN Web Doc: Specifying the range and direction of cursors
- abbreviation of "IndexedDB Key Range"
- passed as the 1st argument of
openCursor()
andopenKeyCursor()
- specifying the bounds of the data looking for
- methods:
upperBound()
orlowerBound()
- the bound probably "closed" (including the given value(s)) or "open" (excluding the given value(s))
-
Example: range of cursor