1.7. 核心API

本文详细探讨了CouchDB。它显示了所有的细节和聪明的地方。我们将向您展示最佳实践并指导您避开常见的陷阱。

我们首先回顾一下在上一个文档中运行的基本操作 入门 从幕后看。我们还展示了Fauxton在用户界面后面需要做些什么,以提供我们之前看到的好特性。

本文既是对核心couchdbapi的介绍,也是一个参考。如果您不记得如何运行某个特定的请求或为什么需要某些参数,您可以随时返回此处查找(我们可能是本文档的最重要用户)。

在解释API的细节时,我们有时需要绕道更大的一段路来解释特定请求的推理。这是一个很好的机会来告诉你为什么CouchDB是这样工作的。

API可细分为以下部分。我们将逐一探讨:

1.7.1. 服务器

这是一个基本的和简单的。它可以作为一个健全性检查来查看CouchDB是否正在运行。它还可以充当需要特定版本CouchDB的库的安全保护。我们用的是 curl 再次强调效用:

curl http://127.0.0.1:5984/

CouchDB回答道,都很兴奋要开始工作了:

{
  "couchdb": "Welcome",
  "version": "3.0.0",
  "git_sha": "83bdcf693",
  "uuid": "56f16e7c93ff4a2dc20eb6acc7000b71",
  "features": [
    "access-ready",
    "partitioned",
    "pluggable-storage-engines",
    "reshard",
    "scheduler"
  ],
  "vendor": {
    "name": "The Apache Software Foundation"
  }
}

返回一个JSON字符串,如果将其解析为编程语言的本机对象或数据结构,则可以访问欢迎字符串和版本信息。

这不是非常有用,但它很好地说明了CouchDB的行为方式。发送一个HTTP请求,结果在HTTP响应中收到一个JSON字符串。

1.7.2. 数据库

现在让我们做一些更有用的事情: 创建数据库 . 严格来说,CouchDB是 数据库管理系统 (DMS)。这意味着它可以保存多个数据库。数据库是一个存储“相关数据”的存储桶。稍后我们将探讨这到底意味着什么。实际上,术语是重叠的——人们通常将DMS称为“数据库”,DMS中的数据库也称为“数据库”。我们可能会遵循这一点,所以不要被它弄糊涂。一般来说,如果我们谈论的是整个CouchDB或CouchDB中的单个数据库,那么应该从上下文中清楚地看到。

现在让我们做一个!我们想存储我们最喜欢的音乐专辑,我们创造性地给我们的数据库命名专辑。请注意,我们现在使用 -X 再次告诉curl发送 PUT 请求而不是默认值 GET 要求:

curl -X PUT http://admin:password@127.0.0.1:5984/albums

CouchDB回复:

{"ok":true}

就这样。你创建了一个数据库,CouchDB告诉你一切进展顺利。如果您试图创建一个已经存在的数据库,会发生什么?让我们再次尝试创建该数据库:

curl -X PUT http://admin:password@127.0.0.1:5984/albums

CouchDB回复:

{"error":"file_exists","reason":"The database could not be created, the file already exists."}

我们返回一个错误。这很方便。我们还了解了CouchDB是如何工作的。CouchDB将每个数据库存储在一个文件中。很简单。

让我们创建另一个数据库,这次使用curl -v (对于“verbose”)选项。verbose选项告诉curl,不仅要向我们显示基本内容(HTTP响应体),还要显示所有底层请求和响应的详细信息:

curl -vX PUT http://admin:password@127.0.0.1:5984/albums-backup

curl阐述:

* About to connect() to 127.0.0.1 port 5984 (#0)
*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)
> PUT /albums-backup HTTP/1.1
> User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
> Host: 127.0.0.1:5984
> Accept: */*
>
< HTTP/1.1 201 Created
< Server: CouchDB (Erlang/OTP)
< Date: Sun, 05 Jul 2009 22:48:28 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 12
< Cache-Control: must-revalidate
<
{"ok":true}
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

真是一口。让我们一行一行的来了解发生了什么,找出什么是重要的。一旦您多次看到这个输出,您将能够更容易地发现重要的部分。:

* About to connect() to 127.0.0.1 port 5984 (#0)

这是curl,告诉我们它将建立到我们在请求URI中指定的CouchDB服务器的TCP连接。一点也不重要,除非在调试网络问题时。:

*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)

curl告诉我们它成功地连接到CouchDB。同样,如果你不想发现你的网络有问题,那就不重要了。

以下行以前缀 >< 字符。这个 > 意味着该行被逐字发送到CouchDB(没有实际的 > )这个 < 意思是这条线是CouchDB送回curl的。:

> PUT /albums-backup HTTP/1.1

这将启动一个HTTP请求。它 方法PUT , the URI/albums-backup ,而HTTP版本是 HTTP/1.1 . 也有 HTTP/1.0 ,这在某些情况下比较简单,但出于所有实际原因,您应该使用 HTTP/1.1 .

接下来,我们会看到一些 请求报头 . 这些用于提供有关CouchDB请求的其他详细信息。:

> User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3

用户代理头告诉CouchDB哪个客户端软件正在执行HTTP请求。我们没有学到什么新东西:那是卷曲。当服务器端的响应中存在已知的错误时,通常需要为服务器端的响应做准备。它也有助于确定用户所在的平台。这些信息可用于技术和统计原因。对于CouchDB User-Agent 标题无关紧要。:

> Host: 127.0.0.1:5984

这个 Host 页眉是必需的 HTTP 1.1 . 它告诉服务器请求附带的主机名。:

> Accept: */*

这个 Accept header告诉CouchDB curl接受任何媒体类型。稍后我们将研究为什么这是有用的。:

>

空行表示请求头现在已经完成,其余的请求包含我们要发送到服务器的数据。在本例中,我们不发送任何数据,因此curl输出的其余部分专用于HTTP响应。:

< HTTP/1.1 201 Created

CouchDB的HTTP响应的第一行包含HTTP版本信息(同样,为了确认请求的版本可以被处理),一个HTTP 状态码 和A 状态代码消息 . 不同的请求触发不同的响应代码。有一系列的命令告诉客户机(在我们的例子中是curl)请求对服务器有什么影响。或者,如果发生错误,是什么类型的错误。 RFC 2616 (http1.1规范)为响应代码定义了清晰的行为。CouchDB完全遵循RFC。

这个 201 Created 状态代码告诉客户机请求所针对的资源已成功创建。这里并不奇怪,但是如果您还记得,当我们尝试创建这个数据库两次时,我们收到了一条错误消息,那么您现在知道这个响应可能包含一个不同的响应代码。根据响应代码对响应进行操作是一种常见的做法。例如,所有的响应代码 400 Bad Request 或者更大的告诉你发生了一些错误。如果您想简化逻辑并立即处理错误,只需选中a>= 400 响应代码。:

< Server: CouchDB (Erlang/OTP)

这个 Server 收割台有助于诊断。它告诉我们所使用的CouchDB版本和Erlang的底层版本。一般来说,您可以忽略这个头文件,但是如果您需要的话,最好知道它在那里。:

< Date: Sun, 05 Jul 2009 22:48:28 GMT

这个 Date 标头告诉您服务器的时间。由于客户机和服务器时间不一定是同步的,所以这个头纯粹是信息性的。你不应该在此基础上构建任何关键的应用程序逻辑!:

< Content-Type: text/plain;charset=utf-8

这个 Content-Type header告诉您HTTP响应正文是哪种MIME类型及其编码。我们已经知道CouchDB返回JSON字符串。适当的 Content-Type 页眉是 application/json . 为什么我们看到了 text/plain ? 这就是实用主义战胜纯洁的地方。发送 application/json Content-Type header将使浏览器向您提供返回的JSON以供下载,而不只是显示它。由于能够从浏览器测试CouchDB非常有用,CouchDB发送一个 text/plain 内容类型,因此所有浏览器都将JSON显示为文本。

注解

有一些扩展可以让您的浏览器感知JSON,但默认情况下不会安装它们。要了解更多信息,请查看 JSONView 扩展,可用于Firefox和Chrome。

你还记得吗 Accept 请求头及其设置方式 */* 表达对任何一种MIME类型的兴趣?如果你发送 Accept: application/json 在您的请求中,CouchDB知道您可以使用适当的 Content-Type 将使用它代替 text/plain . ::

< Content-Length: 12

这个 Content-Length header只是告诉我们响应主体有多少字节。:

< Cache-Control: must-revalidate

这个 Cache-Control header告诉您,或者CouchDB和您之间的任何代理服务器,不要缓存此响应。:

<

这个空行告诉我们,我们已经完成了响应头,接下来的是响应主体。

{"ok":true}

我们以前见过。:

* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

最后两行是curl,告诉我们它让它在开始时打开的TCP连接打开一段时间,但是在收到整个响应之后关闭它。

在整个文档中,我们将使用 -v 选项,但是我们将省略这里看到的一些头,只包括那些对特定请求很重要的头。

创建数据库是很好的,但是我们如何摆脱一个呢?简单——只需更改HTTP方法:

> curl -vX DELETE http://admin:password@127.0.0.1:5984/albums-backup

这将删除一个CouchDB数据库。请求将删除存储数据库内容的文件。没有 “你确定吗?” 安全网或任何 “清空垃圾箱” 你要做的魔术删除一个数据库。小心使用此命令。如果没有备份副本,您的数据将被删除,而没有机会轻松恢复。

本节深入到了HTTP,并为讨论其余核心couchdbapi奠定了基础。下一站:文件。

1.7.3. 文件

文档是CouchDB的中心数据结构。毫不奇怪,文档背后的思想就是真实世界的文档——一张纸,如发票、食谱或名片。我们已经了解到CouchDB使用JSON格式来存储文档。让我们看看这个存储在最低层是如何工作的。

CouchDB中的每个文档都有一个 ID . 每个数据库的ID都是唯一的。您可以自由选择任何字符串作为ID,但为了获得最佳结果,我们建议 UUID (或) GUID ),即一个通用(或全局)唯一标识符。uuid是随机数,碰撞概率很低,每个人都可以在数百万年内每分钟生成数千个uuid而不必创建重复的uuid。这是一个很好的方法,可以确保两个独立的人不能用同一个ID创建两个不同的文档。为什么要关心其他人在做什么呢?首先,其他人可能在以后成为您,或者在另一台计算机上;其次,CouchDB复制允许您与其他人共享文档,并使用uuid确保一切正常。但稍后再详细说明;让我们制作一些文件:

curl -X PUT http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters"}'

CouchDB回复:

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"1-2902191555"}

curl命令看起来很复杂,但是让我们将其分解。第一, -X PUT 告诉curl做一个 PUT 请求。后面是指定CouchDB IP地址和端口的URL。URL的资源部分 /albums/6e1295ed6c29495e54cc05947f18c8af 指定相册数据库中文档的位置。数字和字符的野生集合是一个UUID。这个UUID是您文档的ID。最后 -d flag告诉curl使用以下字符串作为 PUT 请求。字符串是一个简单的JSON结构,包括 titleartist 属性及其各自的值。

注解

如果你手头没有UUID,你可以让CouchDB给你一个(事实上,这是我们刚才没有给你看的)。只需发送 GET /_uuids 要求:

curl -X GET http://127.0.0.1:5984/_uuids

CouchDB回复:

{"uuids":["6e1295ed6c29495e54cc05947f18c8af"]}

喂,一个UUID。如果你需要一个以上的,你可以通过 ?count=10 HTTP参数来请求10个uuid,或者真的,任何你需要的数字。

要再次检查CouchDB是否对保存文档撒谎(通常不会),请尝试通过发送GET请求来检索它:

curl -X GET http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

我们希望你能在这里看到一个模式。CouchDB中的所有内容都有一个地址、一个URI,您可以使用不同的HTTP方法来操作这些URI。

CouchDB回复:

{"_id":"6e1295ed6c29495e54cc05947f18c8af","_rev":"1-2902191555","title":"There is Nothing Left to Lose","artist":"Foo Fighters"}

这看起来很像您要求CouchDB保存的文档,这很好。但是您应该注意到CouchDB在JSON结构中添加了两个字段。首先是 _id ,它保存了我们请求CouchDB保存文档的UUID。如果包含文档,我们总是知道它的ID,这非常方便。

第二个领域是 _rev . 它代表 修订 .

1.7.3.1. 修订

如果您想更改CouchDB中的文档,您不会告诉它在特定文档中查找字段并插入新值。相反,您可以从CouchDB加载完整的文档,在JSON结构(或对象,当您进行实际编程时)中进行更改,并将该文档的整个新修订版(或版本)保存回CouchDB中。每个修订都由新的 _rev 价值。

如果要更新或删除文档,CouchDB希望您包括 _rev 要更改的修订的字段。当CouchDB接受更改时,它将生成一个新的修订号。这种机制可以确保,在您请求文档更新之前,其他人在您不知情的情况下进行了更改,CouchDB不会接受您的更新,因为您可能会覆盖您不知道存在的数据。或者简化:谁先保存对文档的更改,谁就获胜。让我们看看如果我们不提供 _rev 字段(相当于提供过期值):

curl -X PUT http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af \
     -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997"}'

CouchDB回复:

{"error":"conflict","reason":"Document update conflict."}

如果您看到这一点,请将文档的最新修订号添加到JSON结构中:

curl -X PUT http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af \
     -d '{"_rev":"1-2902191555","title":"There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997"}'

现在你明白为什么CouchDB会返回这个 _rev 当我们提出最初的要求时。CouchDB回复:

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"2-8aff9ee9d06671fa89c99d20a4b3ae"}

CouchDB接受了您的写作并生成了一个新的修订号。修订号是 MD5哈希 单据的运输表示 N- 表示文档更新次数的前缀。这对于复制非常有用。看到了吗 复制和冲突模型 更多信息。

CouchDB之所以使用这种修订系统,也就是多版本并发控制,有多种原因 (MVCC) . 他们都是携手合作的,这是一个很好的机会来解释其中的一些。

CouchDB使用的HTTP协议的一个方面是它是无状态的。那是什么意思?与CouchDB交谈时,你需要提出请求。发出请求包括打开到CouchDB的网络连接、交换字节和关闭连接。每次你提出请求时都会这样做。其他协议允许您打开连接、交换字节、保持连接打开、稍后交换更多字节(可能取决于开始时交换的字节),最后关闭连接。保持连接打开以便以后使用需要服务器做额外的工作。一种常见的模式是,在连接的生命周期内,客户机对服务器上的数据具有一致的静态视图。管理大量的并行连接是一项重要的工作。HTTP连接通常是短暂的,做出同样的保证要容易得多。因此,CouchDB可以处理更多并发连接。

CouchDB使用MVCC的另一个原因是这个模型在概念上更简单,因此也更易于编程。CouchDB使用较少的代码来实现这一点,并且更少的代码总是好的,因为每行代码的缺陷比率是静态的。

修订系统对复制和存储机制也有积极的影响,但我们将在后面的文档中对此进行探讨。

警告

条款 版本修订 听起来可能很熟悉(如果你在编程时没有版本控制,现在就停止阅读本指南,开始学习一个流行的系统)。使用新版本进行文档更改的工作原理与版本控制非常相似,但有一个重要区别: CouchDB does not guarantee that older versions are kept around. Don't use the ``_rev`` token in CouchDB as a revision control system for your documents.

1.7.3.2. 详细文件

现在让我们用curl来仔细看看我们的文档创建请求 -v 标志,在我们之前研究数据库API时非常有用。这也是创建更多文档的好机会,我们可以在后面的示例中使用这些文档。

我们将添加更多我们最喜欢的音乐专辑。从 /_uuids 资源。如果你不记得那是怎么回事,你可以回头查几页。:

curl -vX PUT http://admin:password@127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 \
     -d '{"title":"Blackened Sky","artist":"Biffy Clyro","year":2002}'

注解

顺便说一句,如果你碰巧知道更多关于你最喜欢的相册的信息,不要犹豫添加更多的属性。别担心不知道所有专辑的所有信息。CouchDB的无模式文档可以包含您知道的任何内容。毕竟,你应该放松,不要担心数据。

现在有了 -v 选项,CouchDB的回复(只显示重要的部分)如下所示:

> PUT /albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 HTTP/1.1
>
< HTTP/1.1 201 Created
< Location: http://127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0
< ETag: "1-e89c99d29d06671fa0a4b3ae8aff9e"
<
{"ok":true,"id":"70b50bfa0a4b3aed1f8aff9e92dc16a0","rev":"1-e89c99d29d06671fa0a4b3ae8aff9e"}

我们要把 201 Created 响应头中的HTTP状态代码,正如我们前面创建数据库时看到的那样。这个 Location header为我们提供了新创建文档的完整URL。还有一个新的标题。安 ETag 在HTTP中,speak标识资源的特定版本。在本例中,它标识了新文档的特定版本(第一个版本)。听起来很熟悉?是的,从概念上讲 ETag 与CouchDB文档修订号相同,CouchDB将修订号用于etag并不奇怪。etag对于缓存基础设施很有用。

1.7.3.3. 附件

CouchDB文档可以有附件,就像电子邮件可以有附件一样。附件由名称标识,并包含其MIME类型(或 Content-Type )以及附件包含的字节数。附件可以是任何数据。将附件视为附加到文档的文件是最容易的。这些文件可以是文本、图像、Word文档、音乐或电影文件。我们做一个吧。

附件有自己的URL,您可以在其中上载数据。假设我们要将唱片集插图添加到 6e1295ed6c29495e54cc05947f18c8af 文件( “没有什么可失去的” ),我们也假设艺术品在一个文件中 artwork.jpg 在当前目录中:

curl -vX PUT http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg?rev=2-2739352689 \
     --data-binary @artwork.jpg -H "Content-Type:image/jpg"

注解

这个 --data-binary @ 选项告诉curl将文件内容读入HTTP请求主体。我们用的是 -H 选项告诉CouchDB我们正在上传一个JPEG文件。CouchDB将保留这些信息,并在请求此附件时发送适当的头;如果是这样的图像,浏览器将呈现图像,而不是提供数据供您下载。这个稍后会派上用场。请注意,您需要提供要附加插图的文档的当前修订号,就像您要更新文档一样。因为,毕竟,附加一些数据会改变文档。

现在,如果您将浏览器指向http://127.0.0.1:5984/相册/6e1295ed6c29495e54cc059447f18c8af/艺术品.jpg

如果您再次请求文档,您将看到一个新成员:

curl http://admin:password@127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

CouchDB回复:

{
    "_id": "6e1295ed6c29495e54cc05947f18c8af",
    "_rev": "3-131533518",
    "title": "There is Nothing Left to Lose",
    "artist": "Foo Fighters",
    "year": "1997",
    "_attachments": {
        "artwork.jpg": {
            "stub": true,
            "content_type": "image/jpg",
            "length": 52450
        }
    }
}

_attachments 是键和值的列表,其中的值是包含附件元数据的JSON对象。 stub=true 告诉我们这个条目只是元数据。如果我们使用 ?attachments=true 当请求这个文档时,我们将得到一个 Base64 包含附件数据的编码字符串。

稍后,我们将在探索CouchDB的更多特性(例如复制)时了解更多的文档请求选项,这是下一个主题。

1.7.4. 复制

CouchDB复制是一种同步数据库的机制。很像 rsync 本地或通过网络同步两个目录,复制在本地或远程同步两个数据库。

在一个简单的 POST 请求,你告诉CouchDB 来源 以及 目标 和CouchDB将找出哪些文档和新的文档修订版本 来源 还没开始 目标 ,并将继续移动丢失的文档和修订。

我们将深入研究文档中的复制 复制简介 ;在本文档中,我们将向您展示如何使用它。

首先,我们将创建一个目标数据库。请注意,CouchDB不会自动为您创建一个目标数据库,如果目标不存在,它将返回一个复制失败(源数据库也是如此,但是这个错误不那么容易犯)::

curl -X PUT http://admin:password@127.0.0.1:5984/albums-replica

现在我们可以使用数据库了 albums-replica 作为复制目标:

curl -vX POST http://admin:password@127.0.0.1:5984/_replicate \
     -d '{"source":"http://127.0.0.1:5984/albums","target":"http://127.0.0.1:5984/albums-replica"}' \
     -H "Content-Type: application/json"

注解

从CouchDB 2.0.0开始,这两个复制都需要完全限定的URL sourcetarget 参数。

注解

CouchDB支持这个选项 "create_target":true 在发布到 _replicate 网址。如果目标数据库不存在,它会隐式地创建它。

CouchDB回复(这次我们格式化了输出,以便您更容易地阅读):

{
    "history": [
        {
            "start_last_seq": 0,
            "missing_found": 2,
            "docs_read": 2,
            "end_last_seq": 5,
            "missing_checked": 2,
            "docs_written": 2,
            "doc_write_failures": 0,
            "end_time": "Sat, 11 Jul 2009 17:36:21 GMT",
            "start_time": "Sat, 11 Jul 2009 17:36:20 GMT"
        }
    ],
    "source_last_seq": 5,
    "session_id": "924e75e914392343de89c99d29d06671",
    "ok": true
}

CouchDB维护 会话历史记录 复制。复制请求的响应包含此的历史记录项 复制会话 . 还值得注意的是,在复制关闭之前,复制请求将保持打开状态。如果您有很多文档,则需要一段时间才能将其全部复制,并且在复制所有文档之前,您将无法返回复制响应。需要注意的是,复制只复制启动复制时的数据库。因此,在复制开始之后的任何添加、修改或删除都不会被复制。

我们再讨论一下细节 "ok": true 最后告诉我们一切都很顺利。如果现在查看相册副本数据库,应该会看到在相册数据库中创建的所有文档。整洁,是吗?

您刚才所做的就是CouchDB术语中的本地复制。您创建了数据库的本地副本。这对于备份或保留数据特定状态的快照以便以后使用非常有用。如果您正在开发应用程序,但希望能够回滚到代码和数据的稳定版本,则可能需要这样做。

在其他情况下,有更多类型的复制非常有用。我们的复制请求的源成员和目标成员实际上是链接(比如在HTML中),到目前为止,我们已经看到了与我们正在工作的服务器相关的链接(因此是本地的)。也可以将远程数据库指定为目标:

curl -vX POST http://admin:password@127.0.0.1:5984/_replicate \
     -d '{"source":"http://127.0.0.1:5984/albums","target":"http://example.org:5984/albums-replica"}' \
     -H "Content-Type:application/json"

使用A 本地来源 和A 远程目标 数据库被调用 推送复制 . 我们正在将更改推送到远程服务器。

注解

因为我们还没有第二个CouchDB服务器,所以我们只使用单个服务器的绝对地址,但是您应该能够从中推断出可以在其中放置任何远程服务器。

这对于与远程服务器或隔壁伙伴共享本地更改非常有用。

也可以使用 远程源 和A 局部目标 做一个 拉式复制 . 这对于从其他人使用的服务器获取最新更改非常有用:

curl -vX POST http://admin:password@127.0.0.1:5984/_replicate \
     -d '{"source":"http://example.org:5984/albums-replica","target":"http://127.0.0.1:5984/albums"}' \
     -H "Content-Type:application/json"

最后,您可以运行远程复制,这对管理操作非常有用:

curl -vX POST http://admin:password@127.0.0.1:5984/_replicate \
     -d '{"source":"http://example.org:5984/albums","target":"http://example.org:5984/albums-replica"}' \
     -H"Content-Type: application/json"

注解

CouchDB和REST

CouchDB以拥有 RESTful API,但这些复制请求在训练有素的人看来不太稳定。怎么回事?虽然CouchDB的核心数据库、文档和附件API是RESTful的,但CouchDB的API并不是全部都是RESTful。复制就是一个例子。还有更多,我们将在后面的文档中看到。

为什么这里混合了RESTful和非RESTful api?开发商是不是一路懒得去休息?记住,REST是一种架构风格,它适合于某些架构(比如CouchDB文档API)。但这并不是一刀切。在其他世界中,触发类似复制的事件并没有什么意义。它更像一个传统的远程过程调用。这没什么不对的。

我们非常相信“为工作使用正确的工具”的理念,而REST并不适合所有的工作。为了获得支持,我们参考了Leonard Richardson和Sam Ruby RESTful Web Services (O'Reilly),因为他们同意我们的观点。

1.7.5. 总结

这仍然不是完整的couchdbapi,但是我们详细讨论了其中的要点。我们要边走边补。现在,我们相信您已经准备好开始构建CouchDB应用程序了。