CouchDB 是用 Erlang 开发的数据库系统,它不是传统的关系数据库,而是一个面向文档(Document)的数据库系统。它提供了基于 MapReduce 编程模型的视图来对文档进行查询和索引,这类似于关系数据库中 SQL 语句的功能;提供了 RESTFul JSON API,从而可以被任何允许 HTTP 请求的环境所访问,这样 CouchDB 应用可以通过浏览器中的 HTTP 请求直接与数据库交互。CouchDB 最大的意义在于它是一个面向 Web 应用的新一代存储系统。
CouchDB 是:
一个文档数据库服务器,通过 RESTFul JSON API 访问;
模式(Schema)自由:并不要求文档具有某种特定的结构;
分布式的,性能稳健的,增量复制的,具有双向冲突检测和管理的;
能够查询和检索的。
CouchDB 不是:
一个关系型数据库;
一个关系型数据库的替代;
一个面向对象的数据库,具体来说,基于面向对象语言的具有无缝持久层功能的数据库。
CouchDB 特点:
CouchDB 是分布式的数据库,可以把存储系统分布到多台物理的节点上,并很好地协调和同步节点之间的数据读写一致性,这得益于 Erlang 语言的并发性能。对于基于 Web 的大规模应用文档,它的分布式可以让它不必像传统的关系数据库那样分库拆表,在应用代码层进行大量的改动;
CouchDB 是面向文档的数据库,存储半结构化的数据,由于文档没有模式,很适合 CMS、电话本、地址本等应用,在这些场合,文档数据库要比关系型数据库更加方便,性能更优;
CouchDB 支持 RESTFul API,可以让用户使用 JavaScript 来操作 CouchDB 数据库,也可以 JavaScript 编写查询语句,进而于也可以和 Ajax 技术结合。
CouchDB 基本概念
文档(Documents)
一个 CouchDB 数据库的存储实际就是一系列文档的集合,这些文档没有层次结构,因此文档是 CouchDB 的核心,也是 CouchDB 的基本数据存储单元,在 CouchDB 中文档以 JSON 对象的形式保存。每个文档是一系列数据项的集合,每个数据项是一个个键值对,其中值可以是字符串、数字、日期甚至可以是序列表和关联映射,一个样例文档可以如下表示:
"Subject": "I like Plankton" "Author": "Rusty" "PostedDate": "5/23/2006" "Tags": ["plankton", "baseball", "decisions"] "Body": "I decided today that I don't like baseball. I like plankton." |
每个文档都有自己的全局唯一的标识符和版本修订号。ID 用来标识一个文档,而修订版本号用来实现多版本并发控制。
视图(Views)
为了解决向半结构化数据中加入结构化数据的问题,CouchDB 引入了用 JavaScript 描述的视图模型。视图是 CouchDB 中文档的表现方式,是操作文档方法的集合,如过滤、组织、聚合等。视图是动态建立的,并不影响底层的文档,对于同样的文档数据你可以拥有不同的表现视图。
模式自由(Schema free)
不像用来存储高结构化,互相关联数据的关系数据库,CouchDB 被设计用来存储半结构化,基于文档的数据,CouchDB 很大程度上简化了基于文档应用程序的开发。
在关系数据库中,如果数据库原始的设计不能满足新的需求,必须重新进行设计。在 CouchDB 中,模式自由,新的文档类型可以安全地添加到旧文档类型中,视图这时候就可以用来简单地处理新文档类型。
CouchDB RESTFul API
CouchDB 提供 RESTFul API 来使用 CouchDB 的功能,并对数据库进行操作。
数据库 API
- GET /_all_dbs 返回这个服务器上所有数据库的一个列表,列表以 JSON 数组的形式表示;
- GET /dbname 返回名为 dbname 的数据库具体信息,信息以 JSON 对象表示;
- PUT /dbname 创建名为 dbname 的数据库,创建成功则返回 201 的 HTTP 状态码,否则返回 412 的 HTTP 状态码;
- DELETE /dbname 删除名为 dbname 的数据库,如果删除成功,返回 200 的 HTTP 状态码,否则返回 404 的 HTTP 状态码;
文档 API
- GET /dbname/doc_id 返回数据库 dbname 中 ID 为 doc_id 的文档内容,文档内容以 JSON 对象形式表示;
- PUT /dbname/doc_id 在数据库 dbname 中创建 ID 为 doc_id 的文档,如果 doc_id 已存在,则会更新已有的文档,这种情况下 PUT 请求内容的文档中需要包含 _rev 字段,表示文档的修订版本号。CouchDB 使用该字段做更新时的冲突检测。更新完成后,返回 201 的 HTTP 状态码,表示更新成功,若返回 409 的 HTTP 状态码,表示有版本冲突;
- DELETE /dbname/doc_id 在数据库 dbname 中删除 ID 为 doc_id 的文档。
CouchDB 功能优点
CouchDB 不仅是一个数据库服务器(上面的介绍我们都是在描述它作为数据库的特性),同时也是一个应用服务器(下面的示例将用到它作为应用服务器的特性)。CouchDB 的 RESTFul API 使用 JSON 作为展现形式,CouchDB 的应用只需要编写浏览器端的代码就可以使用 JavaScript 与应用服务器进行交互,而 CouchDB 具有的附件功能可以保存基于浏览器的 HTML、JavaScript 和 CSS 代码。这样 CouchDB 不但保存了 Web 应用所需要的数据,也保存了 Web 应用的逻辑,因此只需要这个既可以做数据服务器又可以做应用服务器的 CouchDB 就可以构建完整的 Web 应用开发运行环境。
图 1. 使用 CouchDB 系统处理流程
- 操作系统:Ubuntu 10.0.4
- 需要的项目:CouchDB、CouchApp
- 安装 CouchDB:
清单 1.CouchDB 安装步骤
sudo su # 安装 CouchDB 需要的依赖包 apt-get build-dep couchdb cd /opt |
# 从http://couchdb.apache.org/downloads.html下载最新的 CouchDB 包。
# wget <url>
tar xvzf apache-couchdb-x.xx.x.tar.gz
cd apache-couchdb-x.xx.x
./configure --prefix= --with-js-lib=/usr/lib/xulrunner-devel-x.x.x.x/lib
--with-js-include=/usr/lib/xulrunner-devel-x.x.x.x/include
# 测试安装
make check
# 编译并安装 CouchDB
make && make install
# 修改 /etc/passwd,将 home directory 该为 /usr/local/var/lib/couchdb/, couchdb 的用户在编译和
# 安装时已被添加
# 将文件的所有权从 root 改为 couchdb 用户,并且改变权限
chown -R couchdb: /usr/local/var/{lib,log,run}/couchdb /usr/local/etc/couchdb
chmod 0770 /usr/local/var/{lib,log,run}/couchdb/
chmod 664 /usr/local/etc/couchdb/*.ini
chmod 775 /usr/local/etc/couchdb/*.d
# 启动 couchdb
cd /etc/init.d
ln -s /usr/local/etc/init.d/couchdb couchdb
/etc/init.d/couchdb start
# 在系统启动时启动 couchdb
update-rc.d couchdb defaults
# 在 firefox 中输入 http://127.0.0.1:5984/ 检查 couchdb 是否可以运行,显示结果如下:
# {"couchdb":"Welcome","version":"1.0.1"}
|
安装 CouchApp
清单 2 CouchApp 安装步骤
#CouchApp 需要 Python 2.5x 或者更高版本 curl -O http://python-distribute.org/distribute_setup.py sudo python distribute_setup.py easy_install pip # 安装或更新 CouchApp 最新版本 pip install couchapp |
CouchDB 的应用程序可以通过 CouchApp 部署。CouchApp 有两条基本的命令,分别是 generate 和 push。Generate 用于创建一个应用,所创建的应用有完善的目录结构,下面的示例使用这个目录结构;push 用于将文件系统保存到 CouchDB 的设计文档中。如下面的示例创建一个名为 couchdbtest 的应用,并将它的内容保存到名为 apple 的 CouchDB 数据库上。
-
生成样例应用 couchdbtest
命令:couchapp generate couchdbtest
图 2. 生成应用的目录结构
-
部署应用 couchdbtest 到 CouchDB Server apple 上
命令:couchapp push apple
图 3. 应用部署成功的状态
之后可以通过在浏览器中输入以下网址访问刚创建的应用:
http://127.0.0.1:5984/apple/_design/couchdbtest/index.html
Flex 作为一款强大的矢量动画编辑工具,它涵盖了支持 RIA(Rich Internet Applications) 的开发和部署的一系列技术组合,并且在 RIA 富客户端应用中占据霸主地位。它推出了面向对象的编程脚本 ActionScript 3.0,并且建立起类似于 Java Swing 的类库和相应 compoment。Flex 通过 Java 或 .NET 等非 Flash 途径,解释 .mxml 文件组织 compoments,并生成相应的 .swf 文件。
Flex 较之 Flash 更适合开发者,Flash 天生是为 designer 设计的,而 Flex 用非常简单的 .mxml 来描述界面,跟 jsp/asp/php 程序人员使用的 .(x/d)html 非常相似,而且 mxml 更加规范化、标准化;Flex 的目标是让程序人员更快更简单地开发 RIA 应用。在多层开发模型中,Flex 应用属于表现层。
前面我们讲解了 CouchDB 的特点,基本概念和安装部署,在这个应用中选择 Flex 作为表现层来展开我们的示例程序,以进一步理解 CouchDB 应用的开发过程。
新建 Flex Project
图 4. 新建项目
图 5. 目录结构
修改 Sample.mxml 文件
Sample 将 CouchDB 的 service 以 HTTPService 的方式暴露,通过 GET 方法调用 API /apple/2rb128 以获得 apple 数据库中 id 为 2rb128 的文档内容。
程序以 Button 触发索引数据库事件,将从数据库中取得的数据显示在 DataGrid 中。DataGrid 中有两个 column:key 和 value,分别对应于从数据库中得到数据的键和值。在处理触发事件中,主要完成对 JSON 对象的解析:将字符串形式的 JSON 对象转换成类似于 Map 的键值对形式,然后将这个类 Map 的 ArrayCollection 绑定到 DataGrid 中,则 ArrayCollection 的动态变化能够实时映射到 DataGrid 的视图显示中。
清单 3.Sample.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[ Bindable ]
/* 变量 dataArr 作为组件 dataGrid 的 dataProvider,存放包含键值对的对象
* 变量 text 用来保存 request 返回的文本形式
* 变量 itemStr 则 dataArr 中对象的 String 形式
* 将 text 文本分割为一个个 String 对象保存入 itemStr 中,然后将 itemStr 中的对象
* 一个个封装成键值对对象
*/
public var dataArr:ArrayCollection = new ArrayCollection();
public var text:String;
public var itemStr:ArrayCollection = new ArrayCollection();
//getDBInfo 作为 button 点击的事件处理函数,用于发送 HTTP 请求
private function getDBInfo(): void
{
getdbp.cancel();
getdbp.send();
}
/*resultHandler 作为对 HTTP 请求返回结果的处理函数,完成 JSON 对象在 dataGrid 中的
* 显示
*/
private function resultHandler(event:ResultEvent): void
{
dataArr.removeAll();
/* 将请求返回的结果分割为一个个以键值对为内容的单位,存储于集合 itemStr
* 中
*/
text = event.result.toString();
var beginIndex:int = text.indexOf( "{" );
var endIndex:int = text.indexOf( "}" );
var textCharStr:String = text.substring(beginIndex+1, endIndex);
var count:int = 0;
for ( var i:int =0;i<textCharStr.length;i++)
{
if (textCharStr.charAt(i)== "," )
{
count++;
}
}
var index:int = 0;
var startFlag:int = -1;
var endFlag:int = 0;
var icount:int = 0;
while (index < textCharStr.length)
{
if (textCharStr.charAt(index)== "," )
{
icount++;
endFlag = index;
var tmp:String = textCharStr.substring(startFlag+1, endFlag);
itemStr.addItemAt(tmp,icount-1);
startFlag = endFlag;
}
if (index == textCharStr.length-1)
{
endFlag = textCharStr.length;
var temp:String = textCharStr.substring(startFlag + 1, endFlag);
itemStr.addItemAt(temp,icount);
}
index++;
}
/* 将存储于 itemStr 中的一个个元素转变为存储键和值对象,存储于集合
*dataArr 中
*/
for ( var i:int = 0;i<count+1;i++)
{
var tmpStr:String = String(itemStr.getItemAt(i));
var flag:int = tmpStr.indexOf( ":" );
var key:String = tmpStr.substring(0,flag);
var value:String = tmpStr.substring(flag+1,tmpStr.length);
if (key.indexOf( "\"" )!=-1&&key.lastIndexOf( "\"" )!=-1)
{
key = key.substring(key.indexOf( "\"" )+1,key.lastIndexOf( "\"" ));
}
if (value.indexOf( "\"" )!=-1&&value.lastIndexOf( "\"" )!=-1)
{
value = value.substring(value.indexOf( "\"" )+1,value.lastIndexOf( "\"" ));
}
var pare:Object = {key:key, value:value};
dataArr.addItem(pare);
}
}
]]>
</mx:Script>
<! — Flex 使用 <mx:HTTPService> 标签发送 POST 和 GET 请求外部数据 -->
<mx:HTTPService id="getdbp" method="GET"
url="/apple/2rb128"
result="resultHandler(event)"
/>
<mx:VBox >
<mx:Button label="GetDBInformation" click="getDBInfo()"/>
<mx:DataGrid id="dataGrid" dataProvider="{dataArr}" height="260" width="200" >
<mx:columns>
<mx:DataGridColumn headerText="key" dataField="key" />
<mx:DataGridColumn headerText="value" dataField="value" />
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:Application>
|
以 Flex Application 的方式运行 Sample.mxml
CouchDBSample 工程的 bin-debug 目录下生成 Sample.html, Sample.swf 等文件,将这些文件拷贝到项目 couchdbtest 的 _attachments 目录下
图 6. 待部署文件
将 couchdbtest 的内容再次部署到 CouchDB Server apple 中
命令:couchapp push apple
在浏览器中访问地址:http://127.0.0.1:5984/apple/_design/couchdbtest/index.html
图 7. 访问界面
点击按钮 GetDBInformation 将获得 apple 数据库中名为 2rb128 的文档中内容:
图 8.DB 中信息显示
本文对 CouchDB 的特点,安装部署,以及基于 FLEX 的简单应用做了一个详细的介绍,要做大规模应用级别的开发还需要深入研究,相信通过本文的介绍,可以帮助你快速的基于这种全新的数据库进行 WEB 开发。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 示例代码 | couchdbtest.zip | 1127KB | HTTP |
学习
-
关于 CouchDB 文档,请参考 CouchDB developer document。
-
关于 Flex 3 入门资料,请参考 Getting Started with Flex 3。
-
关于 Flex 3 语言参考,请参考 Flex 3 Language References。
-
关于 Flex 3 SDK 相关参考,请参考 Live Documentation For the Flex SDK。
-
developerWorks Web development
专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
-
developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
-
developerWorks Web 2.0 资源中心,这是有关 Web 2.0 相关信息的一站式中心,包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。您还可以通过 Web 2.0 新手入门栏目,迅速了解 Web 2.0 的相关概念。
讨论
- 加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。