65.9K
CodeProject 正在变化。 阅读更多。
Home

开始使用 PouchDB - 第 1 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (12投票s)

2019年1月15日

CPOL

7分钟阅读

viewsIcon

11614

downloadIcon

107

随着越来越多的用户在移动设备上与 Web 应用程序进行交互,软件开发人员允许他们离线工作变得越来越重要;PouchDB 可以提供帮助。

引言

随着越来越多的用户在移动设备上与 Web 应用程序进行交互,允许他们离线工作变得越来越重要。在许多情况下,用户需要在离线状态下工作,例如在飞机上、在无法进行蜂窝通信的偏远地区,或者在 Wi-Fi 不可用的巨轮上。如果您可以将数据存储在 Web 应用程序本地,即使没有连接,用户也可以继续工作。

您可能会倾向于使用本地存储,但这种方法非常不规范,访问速度慢,并且不允许存储大量数据。另一种方法是使用 WebSQL,它基于 SQLLite。然而,该规范已被弃用,最终将从浏览器中淘汰。另一种方法是 IndexedDB,这是一种非常流行的 JavaScript 数据库,专为 Web 应用程序中的本地存储而设计。然而,IndexedDB 的 API 在不同浏览器之间可能略有差异,并且是基于回调的,而不是使用更现代的基于 Promise 的方法。

现在有了 PouchDB,它在 IndexedDB 之上提供了一个薄的包装器,使所有调用在不同浏览器之间保持一致,并且是基于 Promise 的。这个系列博客文章的第一部分将教您使用 PouchDB 的基础知识。

什么是 PouchDB?

PouchDB 是一个开源的 JavaScript NoSQL 数据库,旨在在浏览器中离线运行。还有一个 PouchDB 服务器版本可以在联机时使用。这两个数据库通过简单的 API 调用进行同步。您也可以在服务器上使用 CouchDB 来同步您的数据。

NoSQL 数据库是一种存储,其中没有像关系数据库那样的固定表结构。NoSQL 数据库有几种不同的方法来存储数据:列式、文档式、图式和键值对。其中,最常见的是列式和文档式。PouchDB 支持面向文档,其中模型中的数据存储为一系列 JSON 对象,每个文档都分配了一个键值。

PouchDB 中的每个文档都必须包含一个名为 _id 的属性。_id 字段的值在数据库中必须是唯一的。您可以为 _id 字段使用任何您想要的 string 值。在本文中,我将使用一个非常简单的值。然而,对于实际应用程序,您可能需要考虑使用 GUID,因为这样可以确保值在与服务器端数据库同步时是完全唯一的。

您可以使用 post()put() 方法将新文档插入数据库,并传入一个 JSON 对象。插入后,您可以通过查找 _id 字段中的值来非常快速地检索该文档,或者您可以使用视图和创建索引来执行其他搜索。

要修改或删除现有文档,您必须首先找到特定文档,然后将整个文档加载到内存中。使用 JavaScript 对任何您想修改的字段进行更改,然后将整个文档保存回数据库。一个名为 _rev 的字段将被创建/更新为新的唯一值,以帮助跟踪哪个文档版本是最新的。

PouchDB 基础知识

为了说明 PouchDB 的基础知识,请创建一个 HTML 项目,并包含 Bootstrap CSS 框架 (www.getbootstrap.com)、PouchDB (www.pouchdb.com) 和 jQuery (www.jquery.com)。添加一个 HTML 页面并添加两个 <div> 语句。第一个 <div> 语句用于显示消息,另一个显示我们 PouchDB 操作返回的 JSON。您可以添加一些 HTML 按钮来调用本文中介绍的各种函数。

<div id="messageArea" class="alert alert-danger hidden">
  <span id="message"></span>
</div>

<div id="jsonArea" class="alert alert-info hidden">
  <textArea id="json" cols="100" rows="30"></textArea>
</div>

通用 JavaScript

创建一个名为 PouchDBSamples-common.js 的 JavaScript 文件,并添加一个包含以下代码的闭包。此闭包中的代码将在我们的每个示例中用于显示消息、显示 JSON 以及清除消息和 JSON 显示区域。

let pouchDBSamplesCommon = (function () {
  //*************************************
  //* Private Functions
  //*************************************
  function displayMessage(msg) {
    $("#messageArea").removeClass("hidden");
    $("#message").text(msg);
    console.log(msg);
  }

  function displayJSON(data) {
    $("#jsonArea").removeClass("hidden");
    $("#json").text(JSON.stringify(data, undefined, 2));
  }

  function hideMessageAreas() {
    $("#messageArea").addClass("hidden");
    $("#message").text("");
    $("#jsonArea").addClass("hidden");
    $("#json").text("");
  }

  //************************************
  //* Public Functions
  //************************************
  return {
    displayMessage: displayMessage,
    displayJSON: displayJSON,
    hideMessageAreas: hideMessageAreas
  }
})();

此闭包中的大多数方法都是不言而喻的,但 displayJSON() 方法可能需要稍作解释。我相信您已经熟悉 JSON.stringify(),但我为它添加了两个额外的参数。第二个参数未使用,因此只需传递 undefined。如果您将数字作为第三个参数传递,它将在字符串化的 JSON 对象中包含指定数量的空格。这将为我们在网页上显示提供格式良好的 JSON 字符串。

打开/创建数据库

在您创建的 HTML 页面上,添加指向 PouchDB、jQuery 和您刚创建的 JavaScript 文件的链接。

<script src="../Scripts/pouchdb-6.4.3.min.js"></script>
<script src="../Scripts/jquery-3.3.1.min.js"></script>
<script src="../Scripts/pouchDBSamplesCommon.js"></script>

在您刚创建的 script 标签正下方添加一个 <script></script> 标签。在这些 script 标签内,创建一个名为 db 的变量。创建一个名为 openCreateDatabase() 的函数,并在该函数内编写代码来创建一个名为 "handyman" 的新 PouchDB 数据库实例。使用 PouchDB 类的 on() 方法响应 "created" 事件。如果 PouchDB 数据库成功打开或创建,则数据库名称将传递给此事件。使用闭包显示数据库已准备就绪的消息。

<script>
  let db = null;

  function openCreateDatabase() {
    db = new PouchDB('handyman');
    PouchDB.on('created', function (dbName) {
      pouchDBSamplesCommon.displayMessage("Database: '" + dbName + "' opened successfully.");
    });
  }
</script>

在页面上添加一个 HTML 按钮来调用 openCreateDatabase() 函数。

<button class="btn btn-primary" onclick="openCreateDatabase();">
  Open/Create Database
</button>

添加一个文档

现在数据库已打开,请调用数据库对象上的 put() 方法将新的 JSON 对象注入数据库。始终使用 put() 方法而不是 post() 方法,因为 put() 会添加或插入文档并设置修订 ID(_rev 字段)。将客户端数据同步到服务器时需要 _rev 字段。

function addTechnician() {
  db.put({
    _id: 'psheriff',
    firstName: 'Pal',
    lastName: 'Sheriss',
    docType: 'technician'
  }).then(function (response) {
    pouchDBSamplesCommon.displayJSON(response);
    pouchDBSamplesCommon.displayMessage("Technician added.");
  }).catch(function (err) {
    pouchDBSamplesCommon.displayMessage(err);
  });
}

获取一个文档

一旦文档在数据库中,您就可以通过将 _id 值传递给 get() 方法来提取它。此方法返回找到的完整文档,如果未找到文档则抛出错误。

function getTechnician() {
  db.get("psheriff")
    .then(function (response) {
      pouchDBSamplesCommon.displayJSON(response);
    }).catch(function (err) {
      pouchDBSamplesCommon.displayMessage(err);
    });
}

更新文档

为了更新文档,您需要先使用 get() 方法检索整个文档。检索到文档后,设置您想要修改的所有属性,调用 put() 方法,并传入更改后的文档。确保返回 put() 方法的输出,这样新的 Promise 就可以被捕获,您可以检查 update 操作的成功或失败。

function updateTechnician() {
  db.get("psheriff")
    .then(function (doc) {
      // Change the document
      doc.firstName = "Paul";
      doc.lastName = "Sheriff";
      // Update the document
      return db.put(doc);
    }).then(function (response) {
      pouchDBSamplesCommon.displayJSON(response);
      pouchDBSamplesCommon.displayMessage("Technician updated.");
    }).catch(function (err) {
      pouchDBSamplesCommon.displayMessage(err);
    });
}

删除文档

在删除文档之前,您需要检索它。将您希望定位的 _id 值传递给 delete。在 then() 函数中,调用 PouchDB 对象上的 remove() 方法。将完整文档传递给 remove() 方法。或者,您可以将 _id_rev 字段的值传递给 remove() 方法。返回 remove() 方法的输出,它是一个 Promise。这样,您就可以检查 remove 操作的成功或失败。

function deleteTechnician() {
  // Get technician
  db.get("psheriff")
    .then(function (doc) {
      // Delete the technician
      return db.remove(doc);
    }).then(function (response) {
      pouchDBSamplesCommon.displayJSON(response);
      pouchDBSamplesCommon.displayMessage("Technician deleted.");
    }).catch(function (err) {
      pouchDBSamplesCommon.displayMessage(err);
    });
}

压缩数据库

当您修改文档时,每次都会存储文档的新修订版本。这意味着随着时间的推移,您将拥有同一文档的许多旧版本。并非所有这些都必需,尤其是在您将数据同步到服务器之后。定期调用 compact() 方法以删除旧数据,以使数据库大小保持合理。

function compactDB() {
  if (db) {
    db.compact().then(function (response) {
      pouchDBSamplesCommon.displayJSON(response);
      pouchDBSamplesCommon.displayMessage("Database compacted");
    }).catch(function (err) {
      pouchDBSamplesCommon.displayMessage(err);
    });
  }
  else {
    pouchDBSamplesCommon.displayMessage("Please open the database first.");
  }
}

删除数据库

如果您不再使用数据库,您可以使用 destroy() 方法将其完全删除。此选项会删除与该数据库相关的所有数据、视图和其他元数据。此操作无法恢复,因此请谨慎操作!

function destroyDatabase() {
  if (db) {
    db.destroy().then(function (response) {
      pouchDBSamplesCommon.displayJSON(response);
      pouchDBSamplesCommon.displayMessage("Database deleted.");
    }).catch(function (err) {
      pouchDBSamplesCommon.displayMessage(err);
    });
  }
  else {
    pouchDBSamplesCommon.displayMessage("Please open the database first.");
  }
}

摘要

在这篇博客文章中,您了解了 PouchDB。您学会了如何创建、更新、删除和读取数据库中的文档。您还了解了如何压缩和删除数据库。在接下来的几期博客文章中,您将学习如何批量插入和读取文档、过滤和计数文档、使用 Mango 查询以及使用 map 和 reduce 函数。有关 PouchDB 的更多信息,请访问我位于 https://blog.fairwaytech.com 的博客。

© . All rights reserved.