IndexedDB - 快速指南


IndexedDB - 简介

数据库管理系统提供了数据存储和检索的机制。有多种可用的数据库,其中最常用的是 -

  • 分层数据库
  • 网络数据库
  • 面向对象的数据库
  • 关系数据库
  • NoSQL 数据库

NoSQL 数据库

NoSQL 数据库(有时称为 Not Only SQL)是一种提供存储和检索数据而不是关系数据库中使用的表格关系的机制的数据库。这些数据库是无模式的,支持轻松复制,具有简单的API,最终一致,并且可以处理大量数据(大数据)。

还有不同类型的 NoSQL 数据库,例如 -

  • 文档数据库。
  • 键值存储。

    面向列的数据库。

    图形数据库。

什么是索引数据库

索引数据库是一种 NoSQL 数据库或非关系结构化查询语言。它是一个事务数据库系统,类似于基于 SQL 的 RDBMS。然而,与使用固定列表的基于 SQL 的 RDBMS 不同,IndexedDB 是基于 JavaScript 的面向对象的数据库。

当我们需要在服务器端存储大量数据并且比本地存储更快时,可以使用它。由于它将数据存储在浏览器中,因此也可以在线和离线使用。使用它,您可以创建一个 Web 应用程序(具有丰富的查询功能),无论互联网连接是否可用,该应用程序都可以运行。

IndexedDB 的主要特征

以下是 IndexedDB 数据库的关键特征 -

IndexedDB 是一种存储键值对的 NoSQL 数据库。它可以通过键或多种键类型存储几乎任何类型的值。

  • 如前所述,IndexedDB 遵循事务数据库模型- 事务是围绕操作或操作组的包装类,以便维护数据完整性。您不希望数据被更改或丢失,因此如果事务失败,则会推出回调。

  • IndexedDB 不使用结构化查询语言- 由于 IndexedDB 使用 NoSQL 数据库,因此它不使用 SQL,而是使用索引查询通过游标或 getAll ()方法来迭代不同的集合来生成数据。

  • IndexedDB 使用大量请求- 请求是接收 DOM 事件成功或失败的对象(DOM - HTML DOM 事件允许 JavaScript 在 HTML 文档中的元素上注册不同的事件处理程序)。DOM 事件是成功或错误,其具有指示请求流的目标属性。

    成功事件无法取消,但错误事件可以取消。IndexedDB 中有很多请求,例如成功请求、错误请求以及addEventListener()、removeEventListener() 请求。为了了解请求的状态,我们还具有就绪状态、结果和错误代码属性。

  • IndexedDB 需要遵循相同的源- 源是正在编写脚本的文档的 URL,每个源下面都有一些数据库,每个数据库都有一个由源标识的名称。IndexedDB 上施加的安全边界可防止应用程序访问不同来源的数据。

    例如,如果我们获取一个 URL 并获取它的不同子目录,它可以检索数据,但如果我们将位置更改为端口 8080 并尝试从常用 URL 和更改后的端口检索数据,我们将无法检索数据。

术语

以下是 indexedDB 中的各种重要术语,在继续操作之前您应该了解这些术语 -

  • 数据库- 在 IndexedDB 中,数据库是最高级别,其中包含包含数据的对象存储。

  • 对象存储- 对象存储是 IndexedDB 的数据存储实体。将其视为 RDBMS 中的表,我们根据要存储的数据类型(例如:id、名称、卷编号等)来存储数据。

  • 事务- 对于任何数据库操作,我们都会执行以下过程。

    • 获取数据库对象
    • 在数据库上打开事务
    • 在事务上打开对象存储,然后对对象存储进行操作。

    所以基本上,事务是一个连接到每个数据库的包装函数,它确保数据完整性,这样如果事务被取消或发生任何错误,它将回调到事务尚未开始的地方。

  • 索引- 将对象存储视为一个表,我们使用索引从中检索单个属性的数据。例如:姓名、年龄等。

  • 游标- 在数据库中,如果我们需要从对象存储中遍历多个记录,我们使用游标。

支持 IndexedDB

IndexedDB 是浏览器中的数据库,因此我们需要检查当前/现有浏览器是否支持它。为此,请将以下代码粘贴到文本编辑器中,将其另存为test.html并在浏览器中运行。

const indexedDB =
   window.indexedDB ||
   window.mozIndexedDB ||
   window.webkitIndexedDB ||
   window.msIndexedDB ||
   window.shimIndexedDB;

if (!indexedDB) {
   document.write("IndexedDB could not be found in this browser.");
}
const request = indexedDB.open("MyDatabase", 1);

如果您的浏览器支持 IndexedDB,则该程序将成功执行,将创建一个数据库。

我的数据库

IndexedDB - 安装

Visual Studio Code是一个重新定义和优化的代码编辑器,用于构建和调试现代 Web 和云应用程序。

  • 您可以从其官方网站下载 Visual Studio Code - https://code.visualstudio.com

  • 根据您的电脑配置和操作系统选择您想要的版本。

  • 下载后,您可以直接将其安装在计算机上。

在 Windows 上安装 Visual Studio Code 安装程序

首先,下载上面指定的 Windows 版 Visual Studio Code 安装程序 -

  • 下载后,运行安装程序。
视觉的
  • 然后,接受协议并单击下一步。
协议
  • 现在,单击“创建桌面图标”,以便可以从桌面访问它,然后单击“下一步”。
设置
  • 然后,单击安装按钮。
安装
  • 最后,安装完成后,点击完成按钮,Visual Studio Code就会打开。

代码设置
  • 现在 Visual Studio code 已成功安装在您的设备上,开始在此代码编辑器上编写代码。

下载、安装和创建 Node.js 项目(可选)

现在安装 Visual Studio 代码后我们需要安装 Node.js

下载 Node.JS

  • 您可以从其官方网站下载 Node.js:https://nodejs.org/en/。

  • 根据您的计算机配置选择您选择的版本。

  • LTS 版本更可取,因为它是更稳定的版本,并且代表长期支持。

安装 Node.js

按照下面给出的步骤在您的系统中安装 Node.js -

步骤 1 - 现在 Node.js 已打开。您会发现弹出此窗口,单击下一步。

Nodejs

步骤 2 - 您将被重定向到“最终用户许可协议”窗口。接受协议并单击“下一步”

Nodejs 设置

步骤 3 - 在下一个窗口中,您需要选择“目标文件夹”。更改现有文件夹,或者使用提到的默认文件夹,然后单击“下一步”

目的地

步骤 4 -在“自定义安装”和“本机模块工具”窗口中单击下一步。

步骤 5 - 现在,安装程序已准备就绪,单击“安装”以安装所选模块。

准备好Nodejs

IndexedDB - 连接

数据库是存储在计算机系统中的结构化数据的有组织的集合。要对数据执行操作,我们需要连接到数据库。在本章中,我们将讨论如何创建/连接数据库、打开数据库和删除数据库。

创建数据库- 您可以使用open()函数在 IndexedDB 中创建数据库。以下是该函数的语法。

let openRequest = indexedDB.open(name, version);

在哪里,

  • name是您需要创建的数据库的名称。
  • version是要创建的数据库的版本。该参数默认值为1。如果省略该值,则版本被视为1。

您传递给此函数的版本值不应小于(IndexedDB 的)当前版本。如果数据库创建成功,该函数返回 1;如果失败,该函数返回 0。

例子

以下是在 IndexedDB 中创建数据库的示例

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Indexed db</title>
</head>
<body>
   <script>
      //Creating a database
      const request = indexedDB.open("myDatabase", 1);
      if(indexedDB){
         document.write("Database Created......");
      }
   </script>
</body>
</html>

输出

如果将上述代码保存在文件“ test.html ”中并运行它,则浏览器上将显示以下消息 -

Database Created......

确认

由于 IndexedDB 是浏览器的内置数据库,因此您可以在浏览器本身中观察创建的数据库。

右键单击结果页面,单击检查元素并选择应用程序选项卡。如果展开它,您可以看到 IndexedDB 数据库,您可以看到创建的数据库文件,如下所示 -

索引数据库文件

生成处理程序

事件是对 HTML 元素执行操作。使用 JavaScript 我们可以处理这些事件。从现在开始,我们使用 JavaScript 处理程序(为了让这一点更清楚)。

如果请求成功,我们将使用onsuccess事件。

request.onerror = event => {
   // Do something (ex: document.write("error");
};

如果请求失败,我们使用onerror事件。

request.onsuccess = event => {
   // Do something (ex : document.write("success");
};

当您创建数据库或增加现有数据库的版本号时,我们使用onupgradeneeded事件。

request.onupgradeneeded = event => {
   var db = event.target.result;
};

例子

以下示例显示消息“数据库创建成功”。如果数据库创建成功。在这里,我们使用onsuccessonerror处理程序来显示这些消息。

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Handlers</title>
</head>
<body>
   <script>
      const request = indexedDB.open("DATABASE", 1);
      request.onsuccess = function (){
         document.write("Database created successfully...")
      }
      request.onerror = function(){
         document.write("database creation error");
      }
      request.onupgradeneeded = function(event){
         var db = event.target.result;
      }
   </script>
</body>
</html>

输出

如果将上述代码保存在文件“test.html”中并运行它,则浏览器上将显示以下消息 -

Database created successfully...

连接到现有数据库

为了与 IndexedDB 交互,我们使用 JavaScript。我们用 JavaScript 编写的代码并不直接与数据库交互。我们需要使用连接对象来连接数据库来操作数据库的对象。

打开数据库直接创建连接。一个数据库可以有多个连接。当连接最初创建时,它处于打开状态。

您可以使用open()函数(我们用来创建数据库)连接到 IndexedDB 数据库。

句法

以下是连接到现有数据库的语法。

let openRequest = indexedDB.open(name, version);

例子

下面给出了一个使用连接对象与现有数据库交互的 JavaScript 示例 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>OPENING A DATABASE</title>
</head>
<body>
   <script>
      const request = indexedDB.open("DATABASE", 1);
      request.onsuccess = function (){
         document.write("<br> Database created successfully")
      }
      const requestone = indexedDB.open("Database1",2);
      requestone.onsuccess = function(){
         document.write("<br> Database created successfully");
      }
      const requesttwo = indexedDB.open("DATABASE",1);
      requesttwo.onsuccess = function(){
         document.write("<br> Database opened successfully");
      }
   </script>
</body>
</html>

输出

上面的程序在浏览器上打印以下输出 -

Database created successfully 
Database opened successfully 
Database created successfully

如果请求成功,则会调用名为 onsuccess 的事件。

在浏览器中检查数据库的另一种方法

除了inspect元素之外,还有另一种方法可以在浏览器中检查IndexedDB数据库。

右上角会有一个自定义和控制按钮,点击它。

选择列表中的“更多工具”选项,然后选择“开发人员工具”

更多工具

在下一页上,选择“应用程序”选项卡,您可以在其中看到 IndexedDB 数据库。

打开数据库

删除数据库

如果有多余的数据库不需要或者占用了不必要的空间,我们可以将其删除。要删除数据库,我们可以使用deleteDatabase()函数。

以下是deleteDatabase()函数的语法-

let deleteRequest = indexedDB.deleteDatabase(name)

这里,name参数是我们要删除的数据库的名称。

例子

以下示例创建一个名为 TestDatabase 的数据库并使用deleteDatabase()函数删除它。

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Indexed db</title>
</head>
<body>
   <script> 
      const request = indexedDB.open("TestDatabase", 1);
      request.onsuccess = function () {
         document.write("Database Created Successfully");
      }; 
      var req = indexedDB.deleteDatabase("TestDatabase");
      req.onsuccess = function () {
         document.write("Database Deleted Successfully");
      };
      req.onerror = function () {
         document.write("Couldn't delete the database");
      };
   </script>
</body>
</html>

直接从浏览器删除数据库

创建数据库后,您可以直接从浏览器中删除该数据库。为此,请按照以下步骤操作 -

步骤 1 - 使用以下方式之一打开可以在浏览器中查看 IndexedDB 数据库(存储)的页面

  • 检查选项- 右键单击​​ → 检查 → 应用程序或者,

  • 开发人员工具- 自定义和控制选项→更多工具→开发人员工具→应用程序

步骤 2 - 如果扩展 IndexedDB 存储,您可以观察创建的数据库列表,如下所示。

测试

步骤 3 - 单击要删除的数据库。在右侧,您将找到“删除数据库”按钮。如果单击它,该数据库将被删除。

删除数据库

关闭数据库

要关闭数据库,我们需要使用函数IDBDatabase.close()

句法

IDBDatabase.close();

IDBDatabase 接口的close ()方法立即返回并关闭连接。

在所有事务完成之前,连接不会关闭,但是,无法为此连接创建新事务,并且如果关闭操作处于挂起状态,方法会引发异常。

IndexedDB - 对象存储

对象存储是IndexedDB的数据存储。这是存储数据的地方。一个数据库可能有多个对象存储。将它们视为 RDBMS 中的表,我们根据要存储的数据类型来存储数据。

为了确保数据库完整性,只能使用回调函数idb.open()创建和删除对象存储。它包含一个名为createObjectStore()的方法,用于创建对象存储。

创建对象存储

您可以使用createObjectStore()方法创建对象存储。以下是该方法的语法 -

IDBDatabase.createObjectStore(name);
Or,
IDBDatabase.createObjectStore(name, options);

在哪里,

  • 名称是对象存储的名称。
  • options对象可以让我们定义各种配置属性。

例子

以下示例创建一个新数据库并在其中创建一个对象存储 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Creating Object Store</title>
</head>
<body>
   <script>
      var request = indexedDB.open("myDatabase", 2);
      request.onupgradeneeded = event => {
         var db = event.target.result;
         var objectStore = db.createObjectStore("customers");
         document.write("Object store Created Successfully...");
      };
   </script>
</body>
</html>

输出

执行时,上述程序在浏览器上显示以下消息。

Object store Created Successfully...

确认

如果上面的程序执行成功,如果您展开“myDatabase”,您可以看到新创建的对象存储。

客户档案

定义主键

与 RDBMS 类似,我们需要主键来唯一定义对象存储中的某些数据。可以使用密钥路径或密钥生成器通过两种方式完成。

密钥路径和密钥生成器

键路径是始终存在并包含唯一值的属性。我们可以选择一个唯一的值,例如电子邮件地址。

生成器为添加到对象存储中的每个对象创建唯一值。默认情况下,如果我们不提及密钥生成器就会出现。例如,自动增量。

句法

以下是在对象存储上创建键路径的语法。

var objectStore = db.createObjectStore("ObjectStoreName", { keyPath: "primary key, autoincrement/autoDecrement : true" });

例子

在下面给出的示例中,我们使用 JavaScript 创建对象存储的键路径 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>keypath</title>
</head>
<body>
   <script>
      var request = indexedDB.open("myDtabase", 2);
      request.onupgradeneeded = event => {
         var db = event.target.result;
         var objectStore = db.createObjectStore("customers",{keyPath:"id", autoIncrement:true});
         document.write("Object store Created Successfully...");
      };
   </script>
</body>
</html>

输出

执行上面的示例时,它将在浏览器上显示以下文本 -

Object store Created Successfully...

确认

如果上面的程序执行成功,如果你展开“myDatabase”你可以看到新创建的对象存储,如果你点击它你可以观察到为“id”创建了keypath 。

关键路径

当创建新的对象存储时,它们会在 IndexedDB 文件夹中提及,如上所示。

您可以同时使用密钥路径和密钥生成器。如果数据始终是唯一的,我们可以使用键路径,否则如果值发生变化,您可以使用键生成器,如果您想更改每个值的值,但想要给出唯一代表存储的值,我们可以使用两者。

定义索引

索引是一种对象存储。它们用于从引用对象中检索由指定属性存储的数据。索引使用指定的属性作为其键路径,而不是引用存储的主键。

要创建索引,您需要在对象存储实例上调用createIndex()方法。

句法

以下是createIndex()方法的语法-

var myIDBIndex = objectStore.createIndex(indexName, keyPath);
var myIDBIndex = objectStore.createIndex(indexName, keyPath, Parameters);

在哪里,

  • indexName创建的索引的名称。

  • Keypath是创建对象存储时的主要定义

  • 最后一个参数的值可以是唯一的,也可以是多次的

    • 如果你“传递 unique: true”。索引不允许单个键出现重复值。

    • 如果你通过“multi-entry: true”。当 keyPath 解析为数组时,索引将为每个数组元素添加一个条目。如果为 false,它将添加一个包含数组的单个条目。

例子

以下 JavaScript 示例演示了如何创建索引。

<!DOCTYPE html>
<html lang="en">
<head>
   <title>OPENING A DATABASE</title>
</head>
<body>
   <script>
      const dbName = "myDB";
      const studentdata = [
         {name : "jason" , rollno: "160218737028" , branch : "IT"},
         {name : "lokesh" , rollno: "160218735020" , branch : "CSE"},
         {name : "tarun" , rollno: "160218733057" , branch : "EEE"},
         {name : "pranith" , rollno: "160218737029" , branch : "IT"}
      ];
      var request = indexedDB.open("myDB", 2);
      request.onupgradeneeded = event => {
         var db = event.target.result;
         var objectStore = db.createObjectStore("student",{ keyPath :"rollno" });
         objectStore.createIndex("name", "name", { unique: false });
         objectStore.createIndex("branch", "branch", { unique: false });
         objectStore.transaction.oncomplete = event => {
            var objectStore = db.transaction("student", "readwrite").objectStore("student");
            studentdata.forEach(function(student) {
               objectStore.add(student);
            });
         };
      };
   </script>
</body>
</html>

输出

如果您去验证 IndexedDB 数据库myDB的内容并展开它,您可以将创建的表观察为 -

关键价值观

如果单击姓名和学生值,您可以观察索引值:

名称索引

# 密钥(密钥路径:“名称”) 主键(键路径:“rollno”) 价值
0 “杰森” “160218737028”

{名称:'杰森',rollno:'160218737028',分支:

1. 分支:“IT”

2.姓名:“杰森”

3. 卷号: "160218737028"

1 “洛克什” “160218735020”

{名称:'lokesh',rollno:'160218735020',分支:'CSE'}

1. 分支:“CSE”

2.名称:“洛克什”

3. 卷号: "160218735020"

2 “普拉尼思” “160218737029”

{名称:'pranith',rollno:'160218737029',分支:'IT'}

1. 分支:“IT”

2.名称:“普拉尼思”

3. 卷号: "160218737029"

3 “塔伦” “160218733057”

{名称:'tarun',rollno:'160218733057',分支:'EEE'}

1. 分支:“EEE”

2.名称:“塔伦”

3. 卷号: "160218733057"

分行索引

# 键(键路径:“分支”) 主键(键路径:“rollno”) 价值
0 “CSE” “160218735020”

{名称:'lokesh',rollno:'160218735020',分支:'CSE'}

1. 分支:“CSE”

2.名称:“洛克什”

3. 卷号: "160218735020"

1 “EEE” “160218733057”

{名称:'tarun',rollno:'160218733057',分支:'EEE'}

1. 分支:“EEE”

2.名称:“塔伦”

3. 卷号: "160218733057"

2 “它” “160218737028”

{名称:'杰森',rollno:'160218737028',分支:'IT'}

1. 分支:“IT”

2.姓名:“杰森”

3. 卷号: "160218737028"

3 “它” “160218737029”

{名称:'pranith',rollno:'160218737029',分支:'IT'}

1. 分支:“IT”

2.名称:“普拉尼思”

3. 卷号: "160218737029"

删除对象存储

对象存储类似于数据库中的表,当不需要表时我们将其删除。同样,如果不再使用对象存储,您可以将其删除。要删除对象存储,您需要调用deleteObjectStore()函数。

句法

以下是deleteObjectStore()函数的语法-

db.deleteObjectStore("store_name");

其中,store_name 是您需要删除的对象存储的名称。

例子

让我们看一个 JavaScript 示例,该示例删除不再需要的对象存储 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>OPENING A DATABASE</title>
</head>
<body>
   <script>
      const dbName = "Database";
      var request = indexedDB.open("Database", 2);
      request.onupgradeneeded = event => {
         var db = event.target.result;
         var objectStore = db.createObjectStore("student",{ keyPath :"rollno" } );
         var objstore = db.createObjectStore("college",{autoIncrement : true});
         db.deleteObjectStore("college");
      };
   </script>
</body>
</html>

输出

在浏览器中删除 IndexedDB 文件夹中的对象存储之前和之后。

Database
   College − object store
   Student − object store
      Name − index
      Branch − index

Database
   Student − object store
      Name − index
      Branch − index

IndexedDB - 创建数据

在创建数据之前,我们需要知道数据是如何传输的。IndexedDB开启事务,它的每一个数据操作都是在每一个事务内部进行的。每个操作有四个步骤 -

  • 获取数据库对象
  • 在数据库上打开事务
  • 在事务上打开对象存储
  • 对对象存储进行操作

IndexedDB 中的操作是 -

  • 创造
  • 更新
  • 删除

首先,要在数据库中执行任何操作,我们需要打开一个事务。交易打开后,我们需要获取我们需要的对象存储。这些对象存储仅根据创建事务时提到的要求提供。然后可以稍后添加所需的任何数据。

函数用于执行给定的操作(如果有)。例如,我们使用 add() 函数将数据添加到数据库中或添加新条目。

句法

以下是将数据创建到数据库的语法 -

ar request = objectStore.add(data);

我们可以使用add()put()函数将数据添加到对象存储中。

例子

在下面的示例中,我们使用 JavaScript 中的 add() 方法将数据插入到对象存储中 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>creating data</title>
</head>
<body>
   <script>
      const dbName = "Database";
      var request = indexedDB.open("Database", 2);
      request.onupgradeneeded = event => {
         var db = event.target.result;
         var objectStore = db.createObjectStore("student",{ keyPath :"rollno" } );
      };
      request.onsuccess = event => {
         document.write("Database opened successfully");
         var db = event.target.result;
         var transaction = db.transaction("student", "readwrite");
         var objectStore = transaction.objectStore("student");
         objectStore.add({ rollno: 160218737028, name: "jason", branch: "IT" });
         objectStore.add({ rollno: 160218733028, name: "tarun", branch: "EEE" });
         objectStore.add({ rollno: 160218732028, name: "lokesh", branch: "CSE" });
         objectStore.add({ rollno: 160218737025, name: "abdul", branch: "IT" });
         objectStore.add({ rollno: 160218736055, name: "palli", branch: "MECH" });
      }
      transaction.oncomplete = function () {
         db.close();
      };
   </script>
</body>
</html>

输出

0 160218732028
{rollno: 160218732028, name: 'lokesh', branch: 'CSE'}
1 160218733028
{rollno: 160218733028, name: 'tarun', branch: 'EEE'}
2 160218736055
{rollno: 160218736055, name: 'palli', branch: 'CSE'}
3 160218737025
{rollno: 160218737025, name: 'abdul', branch: 'IT'}
4 160218737028
{rollno: 160218737028, name: 'jason', branch: 'IT'}

IndexedDB - 读取数据

我们将数据输入到数据库中,我们需要调用数据来查看变化,也可以用于各种其他目的。

我们必须调用对象存储上的get()方法来读取此数据。get 方法获取要从存储中检索的对象的主键。

句法

var request = objectstore.get(data);

在这里,我们使用 get() 函数请求对象存储来获取数据。

例子

以下示例是请求对象存储获取数据的实现 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         const idquery = store.get(4);
         idquery.onsuccess = function(){
            document.write("idquery",idquery.result);
         }
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

database opened successfully
idquery {id: 4, name: 'abdul', branch: 'IT'} 

IndexedDB - 更新数据

创建数据后,下一步就是对其进行各种操作;所以我们需要定期更新数据。当我们将错误的数据输入数据库时​​,我们还需要更新数据。在这里,我们必须指定一个读写事务,因为我们想要写入数据库,而不仅仅是从中读取。

如果我们想修改它或创建数据库中已存在的条目,我们可以使用put()函数。

句法

var requestUpdate = objectStore.put(data);

我们在发生事务的对象存储上使用put()函数,并且需要更新数据。

例子

让我们看一下下面的脚本,了解如何使用 put() 函数更新或修改对象存储中的数据 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE"});
         const idquery = store.get(4);
         idquery.onsuccess = function(){
            document.write("idquery",idquery.result);
         }
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

database opened successfully
idquery {id: 4, name: 'deevana', branch: 'CSE'} 
Previously the data stored in id: 4 was 
Name: abdul Branch : IT 
But as we updated the entry the values are changed.

IndexedDB - 删除数据

有很多情况我们需要从数据库中删除数据;无论是出于存储目的还是只是删除不需要的数据以释放空间。如果我们想从数据库中删除这些不必要的数据,我们可以使用 .delete() 函数

句法

const request = objectStore.delete(data);

我们使用delete()函数删除数据库中不需要的字段。

例子

让我们看一个删除数据的示例脚本 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE
         const deletename = store.delete(1);
         deletename.onsuccess = function(){
            document.write("id : 1 has been deleted");
         }
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

database opened successfully
id : 1 has been deleted

删除后的数据库id:1 =

0  2
{id: 2, name: 'praneeth', branch: 'CSE'}
1  3
{id: 3, name: 'palli', branch: 'EEE'}
2  4
{id: 4, name: 'deevana', branch: 'CSE'}

IndexedDB - 使用 getAll() 函数

在前面的部分中,我们一次只从存储中检索一个对象。现在我们可以检索对象存储的所有数据或子集。get all 方法使用 getAll() 函数返回对象存储中的所有对象

句法

ObjectStore.getAll(optionalConstraint);

我们可以直接调用 getAll() 以返回对象存储中存储的所有对象,或者我们可以指定一个可选约束,例如来自汽车数据库的红色汽车

例子

在下面的示例脚本中,我们调用 getAll() 方法来一次返回对象存储中存储的所有对象 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
         store.createIndex("branch_db",["branch"],{unique: false});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         const branchIndex = store.index("branch_db");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE"});
         const query = branchIndex.getAll(["IT"]);
         query.onsuccess = function(){
            document.write("query",query.result);
         }
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

database opened successfully
query (1) [{...}]
arg1:(1) [{...}]
0:{id: 1, name: 'jason', branch: 'IT'}
length:1
[[Prototype]]:Array(0)
[[Prototype]]:Object

IndexedDB - 索引

索引是一种对象存储,用于从指定属性存储的引用对象中检索数据。尽管索引位于引用对象存储内部并且包含相同的数据,但它使用指定的属性作为其键路径,而不是引用存储的主键。

索引用于定义数据的唯一约束,它们是在创建对象存储时创建的。要创建索引,请在对象存储实例上调用 createIndex 方法 -

句法

var myIDBIndex = objectStore.createIndex(indexName, keyPath);
var myIDBIndex = objectStore.createIndex(indexName, keyPath, objectParameters);

该方法创建并返回一个索引对象。该方法创建一个采用以下参数的索引 -

  • 索引名称- 索引的名称。

  • Keypath - 我们在这里提到主键。

  • 对象参数- 有两个对象参数。

  • 唯一- 无法添加重复值。

  • 多条目- 如果为 true,则当 keyPath 解析为数组时,索引将为每个数组元素在索引中添加一个条目。如果为 false,它将添加一个包含数组的单个条目。

例子

以下示例显示了对象存储中索引的实现 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
         store.createIndex("branch_db",["branch"],{unique: false});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         const branchIndex = store.index("branch_db");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE"});
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

branchIndex:
1
['CSE']
0: "CSE"
length: 1
4
{id: 4, name: 'deevana', branch: 'CSE'}
branch: "CSE"
id: 4
name: "deevana"
2
['EEE']
0: "EEE"
length: 1
3
{id: 3, name: 'palli', branch: 'EEE'}
branch: "EEE"
id: 3
name: "palli"
3
['IT']
0: "IT"
length: 1
1
{id: 1, name: 'jason', branch: 'IT'}
branch: "IT"
id: 1
name: "jason"

IndexedDB - 范围

当我们不想一次获取所有数据时,我们可以使用范围。当我们想要获取特定范围内的数据时,我们只使用范围。我们使用IDBKeyRange对象定义范围。该对象有 4 个方法,分别是 -

  • 上界()
  • 下界()
  • 边界()
  • 仅有的()

句法

IDBKeyRange.lowerBound(indexKey);
IDBKeyRange.upperBound(indexKey);
IDBKeyRange.bound(lowerIndexKey, upperIndexKey);

以下是各种范围代码的列表 -

编号 范围代码和描述
1

所有键 ≥ a

DBKeyRange.lowerBound(a)

2

所有键 > a

IDBKeyRange.lowerBound(a, true)

3

所有键 ≤ b

IDBKeyRange.upperBound(b)

4

所有键 < b

IDBKeyRange.upperBound(b, true)

5

所有键 ≥ a && ≤ b

IDBKeyRange.bound(a, b)

6

所有键 > a &&< b

IDBKeyRange.bound(a, b, true, true)

7

所有键 > a && ≤ b

IDBKeyRange.bound(a, b, true, false)

8

所有键 ≥ a && < b

IDBKeyRange.bound(a, b, false, true)

9

关键=c

IDBKeyRange.only(c)

我们通常使用索引来使用范围,在语法中,索引键表示索引键路径值。

例子

使用 get() 和 getAll() 方法检索范围代码的各种示例如下 -

class.get(‘student’) 
class.getAll(IDBKeyRange.bound(‘science’,’math’) 
class.getAll(IDBKeyRange.upperbound(‘science’,true) 
class.getAll() 
class.getAllKeys(IDBKeyRange.lowerbound(‘student’,true))

HTML 示例

考虑下面的 HTML 示例来获取范围代码 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
         store.createIndex("branch_db",["branch"],{unique: false});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         const branchIndex = store.index("branch_db");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE"});
         const upperquery =store.getAll(IDBKeyRange.upperBound('2', true));
         upperquery.onsuccess = function(){
            document.write("upperquery",upperquery.result);
         }
         transaction.oncomplete = function(){
            db.close;
         }
      }
   </script>
</body>
</html>

输出

database opened successfully
upperquery (4) [{...}, {...}, {...}, {...}]
arg1: (4) [{...}, {...}, {...}, {...}]
0: {id: 1, name: 'jason', branch: 'IT'}
1: {id: 2, name: 'praneeth', branch: 'CSE'}
2: {id: 3, name: 'palli', branch: 'EEE'}
3: {id: 4, name: 'deevana', branch: 'CSE'}
length: 4
[[Prototype]]: Array(0)
[[Prototype]]: Object

IndexedDB - 交易

事务是一组操作,要么全部成功,要么全部失败。例如,如果我们从 UPI 向商家付款并且交易失败,那么资金必须退回到发件人的帐户。事务可以维护这种完整性。

以下是打开交易的语法 -

db.transaction(store[, type]);

这里的存储是我们要进行事务的对象存储。交易类型有两种 -

  • 只读- 只能读取,默认情况下给出。

  • 读写- 我们只能读取和写入数据,但不能从对象存储中创建、删除或更改它。

交易生命周期

事务是对象存储之间的连接,用于执行任何操作。每笔交易都有一个状态,可以是 -

  • active - 首次创建交易时。或者当请求与事务关联时。当事务处于此状态时,可以针对该事务发出新请求。

  • inactive - 事务在创建后控制权返回到事件后处于此状态。当事务处于这种状态时,不能对事务发出任何请求。

  • 提交- 一旦与事务关联的所有请求完成,它就会尝试提交。在提交状态期间,不能发出新的请求。

  • Finished - 事务提交或中止后,它就处于完成状态。在完成状态期间,不能提出新的请求。

交易的生命周期

一个有范围、有模式的交易就这样形成了。事务在生成时的状态最初是活动的。

  • 要开始事务,实现必须对任务进行排队。

  • 当处理与事务连接的每个请求时,将触发成功或错误事件。发送事件时,事务状态设置为活动状态,允许针对该事务发出后续请求。事件分派完成后,事务的状态将设置为非活动状态。

  • 事务可以在完成之前随时取消,即使该事务当前未处于活动状态或尚未开始。

  • 当针对数据库发出的所有请求都成功时,实现必须尝试提交事务。

  • 当提交或中止事务时,其状态设置为完成。

交易调度

当事务可以启动时,有一些限制。

  • 当没有读或写事务时:是在交易 tx b 之前建立的。与 tx c 有重叠范围。未处于最终状态,可以开始只读事务 tx。

  • 当没有其他事务时,读/写事务 tx 可以开始 -

    • 在 tx 之前形成,
    • 与 tx 有重叠范围,或者
    • 未处于完成状态。

升级交易

模式为“ versionchange ”的事务是升级事务。

可以使用升级操作来创建、重命名和删除数据库中的对象存储和索引。

如果给定的版本高于当前版本,则在打开与数据库的连接后完成运行升级事务的步骤时,会自动生成升级事务。在Upgradeneeded事件处理程序中,此事务将处于活动状态。

进行交易

必须完成以下步骤才能提交事务 -

  • 事务状态首先设置为提交。
  • 等待列表中的所有交易请求均已处理完毕。
  • 如果发生错误,则中止事务。
  • 如果事务是升级事务,则将数据库升级事务的事务连接设置为 NULL。
  • 更改事务状态以完成。
  • 触发交易的整个事件
  • 如果事务是升级事务,则将请求的事务设置为 null 并发出与该事务关联的请求。

句法

transaction.commit()

尝试提交事务。所有待处理的请求将被允许完成,但不会接受新的请求。

如果待处理的请求失败,事务将中止。成功请求的成功事件仍将触发,但在事件处理程序中引发异常不会中止事务,调用PreventDefault()也不会阻止事务中止。

事件处理程序

各种事件处理程序属性如下

attribute EventHandler onabort; 
attribute EventHandler oncomplete; 
attribute EventHandler onerror;

交易示例

下面给出了一个简单的 JavaScript 程序来演示事务的用法 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Document</title>
</head>
<body>
   <script>
      const request = indexedDB.open("botdatabase",1);
      request.onupgradeneeded = function(){
         const db = request.result;
         const store = db.createObjectStore("bots",{ keyPath: "id"});
      }
      request.onsuccess = function(){
         document.write("database opened successfully");
         const db = request.result;
         const transaction=db.transaction("bots","readwrite");
         const store = transaction.objectStore("bots");
         store.add({id: 1, name: "jason",branch: "IT"});
         store.add({id: 2, name: "praneeth",branch: "CSE"});
         store.add({id: 3, name: "palli",branch: "EEE"});
         store.add({id: 4, name: "abdul",branch: "IT"});
         store.put({id: 4, name: "deevana",branch: "CSE"});
         transaction.oncomplete = function(){
            document.write("transaction complete");
            db.close;
         };
      }
   </script>
</body>
</html>

输出

database opened successfully
transaction complete

这里创建了一个事务,只有创建事务后我们才能将数据添加到对象存储中,最后事务完成后我们关闭数据库。

例子

以下示例显示了事务属性 oncomplete 的用法 -

function student(db, names) {
   let transaction = db.transaction(['names'], 'readwrite');
   let store = transaction.objectStore('names');
   for (let i = 0; i < messages.length; i++) {
      store.add({text: names[i]});
   }
   transaction.oncomplete = function()
   {document.write('transaction complete')};
}

中止交易

要中止交易,请按照以下步骤操作 -

  • 对数据库的所有与事务相关的修改都将被撤消。

  • 对象存储、索引和版本中的更改同样会在升级事务期间恢复。

  • 完成交易状态。

  • 如果错误不为空,则将事务错误设置为错误。

  • 对于事务请求列表中的每个请求,将请求已处理标志设置为 true。

  • 将请求完成标志设置为 true 并定义结果。

  • 如果事务是升级事务,则将与事务连接关联的升级事务设置为空。

  • 在事务事件中创建一个中止,并将 bubbles 属性设置为 true。

  • 如果事务是升级事务,则假设该请求是事务的打开请求。

IndexedDB - 错误处理

并非我们编写的所有请求都会返回输出。这可能是由于 -

  • 编写代码时可能出现的错误。
  • 如果超出存储限制。
  • 如果交易失败等。

在失败的请求中,事务被取消,并且所有更改都被恢复。但有时我们希望在不恢复所有更改的情况下处理失败,因此我们使用request.onerror处理程序。它可以通过调用event.preventDefault()来防止事务中止。

例子

下面给出了一个显示 IndexedDB 中错误处理的示例 -

<!DOCTYPE html>
<html lang="en">
<head>
   <title>IndexedDB</title>
</head>
<body>
   <script>
      const request = indexedDB.open("DATABASE", 1);
      request.onsuccess = function (){
         document.write("database creation success")
      }
      request.onerror = function(event){
         document.write("Database not created " + event.target.errorCode);
      }
   </script>
</body>
</html>

输出

Database not created undefined

我们可以使用 db.onerror 处理程序来捕获错误。

db.onerror = function(event) { 
   let request = event.target; 
   document.write("Error is found", request.error); 
};

当具有相同 id 的对象已经存在时,会发生约束错误。但有时,如果任何错误已完全处理并且我们不想报告它,我们可以通过在 request.onerror 中使用event.stopPropagation()来停止冒泡。

request.onerror = function(event) { 
   if (request.error.name == "ConstraintError") { 
      document.write("id already exists"); 
      event.preventDefault(); 
      event.stopPropagation(); 
   }
}

IndexedDB - 搜索

我们遇到很多需要在对象存储中搜索值的情况。对象存储在内部排序。可以通过以下方式完成 -

  • 按键值或键范围搜索。
  • 基于另一个对象字段进行搜索。

按键搜索

我们可以通过使用具有可接受的键范围的 IDBKeyRange 对象来搜索精确的键值或一系列键值。IDBKeyRange 对象有以下调用 -

  • IDBKeyRange.lowerBound(lower, [open]) for >=lower

  • IDBKeyRange.upperBound(upper, [open]) for >=upper

  • IDBKeyRange.bound(lower, upper, [lowerOpen] , [upperOpen]) 介于上下之间

  • IDBKeyRange.only(key) 如果范围仅包含一个键。

为了执行实际的搜索,我们使用对象存储上的查询参数。执行这些操作的不同类型的方法是

  • store.get(query) - 通过键或范围搜索存储中的第一个值

  • store.getAll([query],[count]) - 搜索存储中的所有值,直到达到提到的计数限制。

  • store.getKey(query) - 搜索满足查询的第一个键。

  • store.getAllKeys([query],[count]) - 搜索满足查询的所有键,直到完成计数限制。

  • store.count([query]) - 获取满足查询的键的总数。

例子

在此示例中,我们使用 getAll() 方法检索所有对象并按对象的键搜索对象 -

class.get(‘student’) 
class.getAll(IDBKeyRange.bound(‘science’,’math’) 
class.getAll(IDBKeyRange.upperbound(‘science’,true) 
class.getAll() 
class.getAllKeys(IDBKeyRange.lowerbound(‘student’,true))

按字段或索引搜索

要基于其他对象字段进行搜索,我们需要使用索引。索引存储具有所需值的对象的键列表。索引也像对象存储一样在内部排序。

句法

objectStore.createIndex(name, keyPath, [options]);

名称- 索引名称

keyPath - 搜索将在对象字段的路径上完成

选项- 选项有两种类型

  • unique - 存储中具有唯一值的对象将出现在关键路径上,并且不能对其进行重复。

  • 多条目- 如果键路径上的值是一个数组,那么默认情况下索引会将整个数组视为键,但如果我们使用多条目,则数组成员将成为索引键。

例子

如果我们想根据价格搜索手机,示例程序如下 -

openRequest.onupgradeneeded = function() { 
   let books = db.createObjectStore('phone', {keyPath: 'id'}); 
   let index = books.createIndex('pricephone', 'price'); 
};

要创建索引,我们需要使用所需的升级。

  • 该指数将跟踪价格字段。
  • 如果价格不唯一,我们就无法设置唯一选项。
  • 如果价格不是数组,则 multiEntry 不适用。

例子

在下面的示例中,我们创建一个事务并使用 getAll() 函数检索所有对象。一旦检索到它们,我们就在该事务中搜索对象值。如果找到,则返回该对象;如果不是,则返回 false。

let transaction = db.transaction("phones"); 
let books = transaction.objectStore("phones"); 
let priceIndex = books.index("price_index");
let request = priceIndex.getAll(7); 
request.onsuccess = function() { 
   if (request.result !== undefined) { 
      document.write("Phones", request.result); 
   } else { 
      document.write("There are no such phones"); 
   } 
};

HTML 示例

下面给出了在对象存储中搜索值的 HTML 脚本实现 -