基于分布式数据库的 SQL 同步机制,例如 HTML5 浏览器中嵌入的机制,会导致复杂的工作。Apache CouchDB 具有内在的同步基础。(要获得更多有关 CouchDB 同步的信息,请参考 参考资料。)在本文中,通过查看典型的使用方案来了解 CouchDB 概念和技术细节。您将创建并部署一个简单库存管理应用程序的原型。
虽然在我以前的 developerWorks 文章 “使用 HTML5 创建移动设备上的离线 Web 应用程序” 中介绍了基于 HTML5 概念的类似应用程序,但是并没有处理同步。在本文中,通过使用 CouchDB 环境的存储和标准同步工具,我迁移了应用程序。您可以从下面的 下载表 中下载本文中使用的源代码。
图 1 显示了来自 使用 HTML5 创建移动设备上的离线 Web 应用程序 的 CouchDB 和 HTML5/SQL 解决方案的示例应用程序体系结构主要组件的概述。两个解决方案都包含 HTML、JavaScript、本地数据存储和远程数据存储。
图 1. 脱机 CouchDB 应用程序的核心元素
- HTML 页面
- HTML5 和 CouchDB 应用程序的核心。它具有模型角色并包含已显示的数据和默认呈现信息。页面的 HTML 元素被组织在 HTML 文档对象模型(Document Object Model,DOM)树的层次结构中。
用户发起的事件会导致常规的请求-响应周期,具有页面加载并执行关联的 JavaScript 函数。值得注意的是,这些应用程序包括单一的 HTML 页面,无需通过请求-响应周期加载进一步的 HTML 页面。整个操作都是在一个页面上。
- JavaScript
- 包含 HTML5 和 CouchDB 应用程序的控制器功能。通过针对 JavaScript 功能的事件处理程序绑定 HTML 元素。JavaScript 可访问包含所有用户界面元素的应用程序的 HTML DOM 树并使用它作为计算的数据输入。处理的结果可以通过修改 HTML 页面提供给用户。
- 本地数据存储
- HTML5 应用程序的 SQL 数据库基于模式并使用联接来合并来自多个表的数据。CouchDB 应用程序的数据存储没有模式— 以 JSON 文档形式存储并检索文档。无需使用联接来汇集数据。
为管理数据,SQL 数据库使用 SQL 查询。CouchDB 具有 RESTful 方法:每一个文档都是一个具有用于请求的 HTTP 方法的 RESTful 资源。
- 远程数据存储
- 应用程序基础设施包括相互复制的数据存储节点的网络。在关系 SQL 数据库的世界中,需要编写或管理复杂的复制基础设施。
在 NoSQL CouchDB 体系结构中,提供了一个默认的复制框架。实际上执行冲突文档的合并是特定于应用程序的功能(请参考 参考资料)。这是 CouchDB 最强大的功能之一。
此部分提供示例应用程序 MyHomeStuff 的概述,其提供简单库存管理以便跟踪您自己的物品。它的功能相当于 HTML5 版本。图 2 显示了 Windows® 上的 Firefox® 浏览器中的应用程序。
图 2. Windows 上的 Firefox 浏览器中的库存管理系统
Android™ web 浏览器上的应用程序显示如下。
图 3. Android 上的库存管理系统
该应用程序允许您跟踪自己的物品。屏幕上方的清单给出了所有已输入物品的概述,如书籍。通过在清单上选择物品,物品的详细信息(数量和名称)会显示在中间的表单上。通过使用 Update 按钮可变更已选物品的详细信息,或通过 Delete 按钮将已选物品从应用程序中删除。通过在表单上输入物品的数量和名称并选择 Create,可创建新的物品。
用户可启动屏幕下方的复制过程。该过程通过输入源和目标 CouchDB 的 URL 并激活 Replicate 按钮来操作。目标 CouchDB 可以是现有的远程或本地数据库。
HTML 页面包含声明、外部 JavaScript 文件的引用以及形成应用程序基础结构的必要 HTML 元素。清单 1 显示了该代码。
清单 1. HTML 代码
<!DOCTYPE html>
<html>
<head>
<title>MyHomeStuff2</title>
<script src="/_utils/script/jquery.js"></script>
<script src="/_utils/script/jquery.couch.js"></script>
<script src="script.js"></script>
</head>
<body>
<h3>Overview</h3>
<ul id="itemData" ></ul>
<h3>Details</h3>
<form name="itemForm">
<input type="hidden" name="id" id="idId" />
<input type="hidden" name="rev" id="revId"/>
<label for="amount">Qty: </label>
<input type="text" name="amount" id="amountId" size = 3/>
<label for="name">Name: </label>
<input type="text" name="name" id="nameId" size=12 />
<br><br>
<input type="button" id="createId" value="create" />
<input type="button" id="updateId" value="update" />
<input type="button" id="deleteId" value="delete" />
</form>
<h3>Replicate</h3>
<form>
<label for="sourceDBId">Source: </label>
<input id="sourceDBId" type="text"></input>
<br><br>
<label for="targetDBId">Target: </label>
<input id="targetDBId" type="text"></input>
<br><br>
<input id="replicateId" type="button" value="replicate"></input>
</form>
</body>
</html>
|
因为 jQuery 库用于 JavaScript 部分,HTML 页面不包含事件处理程序属性。从 JavaScript 代码绑定(单击)事件处理程序到 HTML 表单操作。
JavaScript 库 (jquery.couch.js)用于与 CouchDBs 进行交互。通过使用简单的 JavaScript,其简化了通信。例如,您使用 db.saveDoc(aTask),而不是为 RESTful CRUD 操作建立通信(例如,PUT /tutorial/task/4 ...)。
为了开发更先进的应用程序,您应该使用 CouchApp 框架。CouchApp 包括一组可以简化开发 CouchDB 应用程序的脚本(要获得更多信息,请参考 参考资料)。
JavaScript 代码包括三个主要块:
- 初始化函数
- db (crud) 与视图刷新函数
- 复制函数
第一个块包括数据存储和视图的初始化代码,如清单 2 所示。
清单 2. JavaScript
refreshItems 代码
var db = $.couch.db(getCurrentDBName());
function getCurrentDBName() {
return window.location.pathname.split("/")[1];
}
$(document).ready(function() {
//1. init stuff
refreshItems();
$('#sourceDBId').val(db.name);
$('#targetDBId').val(db.name + "-copy");
//2. event handler crud stuff
...
});
function refreshItems() {
$("ul#itemData").empty();
db.view("myDesign/myView", {
success: function(data){
data.rows.map(function(row) {
$('ul#itemData').append('<li id="'+row.value._id+'">'
+row.value.amount
+" x "
+row.value.name
+'</li>');
$('#'+row.value._id).click(function() {
$('#idId').val(row.value._id);
$('#revId').val(row.value._rev);
$('#amountId').val(row.value.amount);
$('#nameId').val(row.value.name);
return false;
});
});
},
error: function(req, textStatus, errorThrown){alert('Error '+ textStatus);}
});
}
|
在上面的代码中:
- 创建 CouchDB 实例。从当前的 URL 中提取数据库名称。
- 在初始化 DOM 以后调用文档
ready函数。首先,其调用refreshItems函数并用源和目标数据库的名称填充复制表单的字段。 refreshItems函数查询现有的记录并用该数据填充 HTML 页面,如下:- 从 DOM 树中删除旧数据。
- 查询 CouchDB。查询并报告 CouchDB 的主要工具是视图。
通过成功处理程序和错误处理程序函数执行查询。视图函数使用 HTTP GET 进行 RESTful 查询。视图包含映射函数,其将具有名称和金额字段的每个文档转换为键值对,其中 ID 为键,文档为值(请参考视图
myView中映射函数的 部署 部分)。 - 成功处理程序为每一个值创建一个 HTML 清单元素并将其添加到清单中。为每一个清单元素添加事件单击处理程序以便通过填充选择的字段对单击作出响应。
- 错误处理程序通过警告对话框显示问题。
事件处理程序位于 refreshItems 函数的第二部分,其包含了按钮栏和更新、删除以及创建的清单。清单 3 显示了 update 的代码。(Create 和 delete 具有相似的结构,因此不在此处显示。您可以从下面的 下载表 中下载示例应用程序的所有源代码。)
清单 3. JavaScript
update 代码
...
//event handler crud stuff
...
$('input#updateId').click(function(e) {
if ($('#idId').val().length == 0) {
return;
}
var aTask = {
_id: $('#idId').val(),
_rev: $('#revId').val(),
amount: $('#amountId').val(),
name:$('#nameId').val()
}
db.saveDoc(aTask, { success: function(resp) {
refreshItems();
}});
});
...
|
在上面的代码中:
- 读取并验证表单的字段值。
- 如果值是有效的,则创建 JSON 对象且使用 HTTP PUT 执行更新调用来进行更新操作。
- 在通过成功处理程序刷新的 HTML 页面中显示查询结果。
复制函数的代码非常密集,如清单 4 所示。
清单 4. JavaScript 复制代码
$('#replicateId').click(function() {
var sourceDB = $('#sourceDBId').val();
var targetDB = $('#targetDBId').val();
$.couch.replicate(sourceDB, targetDB, {
success: function(data){alert('Replication was performed');},
error: function(req, textStatus, errorThrown){alert('Error '+ textStatus);}
});
});
|
在上面的代码中:
- 读取复制表单的字段值。
- 执行复制调用。
- 复制结果显示为警告框,通过成功或错误处理程序激活。
如果您在计算机上安装了 CouchDB,您就可以运行示例。对于 Linux®、Windows、Mac® 和 Android(2.1 或更高;请注意在撰写本文时,Android 端口是 0.50 alpha 版)来说,CouchDB 具有不同的安装程序。此外,您可以使用托管服务。我成功地尝试了 CouchOne 的免费托管(请参考 参考资料)。
在安装 CouchDB 以后,容器就可以按一些步骤输入已下载的应用程序。
- 为应用程序和数据创建数据库。
- 单击 Create Database ...
- 在 Create New Database 对话框中,输入 Database Name 字段(例如 stuff_db)并单击 Create。
- 使用数据(用于测试目的)创建文档。
- 单击 New Document。
- 单击 Add Field。
- 在 Field 中输入
name并在 Value 中输入table。通过绿色复选标记或 tab 键确认。
- 单击 Add Field。
- 在 Field 中输入
amount并在 Value 中输入3。确认。 - 单击 Save Document。
现在,第一个数据已经准备好进行查询。
- 创建一个视图并将其保存为设计文档。
- 选择 Overview --> stuff_db。
- 选择 View: Temporary view... (从左上部的下拉清单)。
- 输入映射函数:
function(doc) { if (doc.name && doc.amount) { emit(doc._id, doc); }}
对于数据库中包含具有非空值的名称和金额字段的每个文档来说,将在视图中创建一个结果行。行的键是文档的 ID;值就是文档本身。
- 单击 Run 进行测试。结果是已输入文档的键值对。
- 单击 Save As...
- 在 Save View As... 对话框中,使用
_design/myDesign填充 Design Document 字段,使用myView填充 View Name: 字段,单击 Save。现在您拥有了存储 CouchDB 应用程序的设计文档。
- 查询视图。
- 在浏览器中输入以下内容:
http://127.0.0.1:5984/stuff_db/_design/myDesign/_view/myView
- 它将显示输入的数据,如下所示:
{"total_rows":1,"offset":0,"rows":[ {"id":"c9938dc172b31a34ef4f0d7f3f000d5d", "key":"c9938dc172b31a34ef4f0d7f3f000d5d", "value":{"_id":"c9938dc172b31a34ef4f0d7f3f000d5d", "_rev":"3-d107f491d254b01c0135fd1e8dd13e0a", "table":null,"name":"table","amount":3}} ]}
(由于格式原因,行被人为中断。) - 使用
http://127.0.0.1:5984/_utils/document.html?stuff_db/_design/myDesign
打开新的设计文档并向设计文档上传附件(用于添加应用程序函数)。 - 通过 File、index.html,选择 Upload Attachment,然后单击 Upload。
- 通过 File、script.js,选择 Upload Attachment,然后单击 Upload。
- 单击 Save Document。
- 通过选择来自具有
http://127.0.0.1:5984/stuff_db/_design/myDesign/index.html
的设计文档的 _attachments 字段的 index.html 值打开应用程序 - 在应用程序中输入并更改一些数据。
在成功安装应用程序以后,通过使用复制机制您可以将其部署到不同的 CouchDB 数据库。
- 为简化问题,请在相同的 CouchDB 节点上创建新的数据库(例如 new-stuff-db)。
- 输入现有 CouchDB 数据库的 URL。在 Source 字段输入源数据库的名称 (stuff_db),并在 Target 字段输入目标 URL (new-stuff-db)。
- 单击 replicate。将复制具有数据和程序代码的整个数据库。
用相同的方法可以将新输入的数据简单地从复制传回到原始数据库。
- 尝试将 CouchDB 数据库复制到远程 CouchDB 节点。
例如,如果您在 CouchOne 主机上注册子域
mysubdomain,并创建名为mydatabase的数据库,则您将使用的目标 URL 是:http://mysubdomain.couchone.com/mydatabase
您在本文中了解了通过 CouchDB 创建脱机应用程序的技术观点。一个简单的库存管理应用程序的原型演示了使用 JSON 存储和标准同步工具的 CouchDB 技术。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 本文源代码 | OfflineCouchDBAppSrc.zip | 3KB | HTTP |
学习
- “使用 HTML5 创建移动设备上的离线 Web 应用程序”(developerWorks,2010 年 5 月),通过 HTML5 标准的简单示例探索了移动应用程序空间中 web 开发的使用。
- 阅读有关 Apache CouchDB 项目的更多信息。
-
CouchOne Mobile for Android 是 CouchDB 的 Android 端口。
- “What the HTTP is CouchApp?
” 提供了技术概述和很好的 “hello world” 示例。
- “面向 PHP 开发人员的 CouchDB 基础知识”(developerWorks,2010 年 3 月)是一篇不错的介绍性文章,其显示了有经验的 PHP 开发人员(和其他人员)如何将 CouchDB 添加到他们的技术工具箱。
- CouchDB wiki 复制和冲突模型 探索了复制和冲突的处理。
- 阅读有关 NoSQL ([Wiki10] Wikipedia) 的更多信息。
- developerWorks 的 developerWorks 中国网站 Web 开发专区 专门提供关于各种 Web 解决方案的文章。
获得产品和技术
- 试用免费的 CouchOne 托管。
- 下载 Apache CouchDB。
-
使用 IBM 产品评估试用版软件 改进您的下一个开发项目,这些软件可以通过下载或从 DVD 获得。
讨论
- 找到 对 web 开发感兴趣的其他 developerWorks 成员。
- 分享您的知识:加入一个关注 web 主题的 developerWorks 群组。
- Roland Barcia 撰写的关于 Web 2.0 和中间件 的博客。
- 关注 developerWorks 成员 关于 web 主题的共享书签。
- 快速找到答案:访问 Web 2.0 Apps 论坛。
