1.1. API基础知识¶
CouchDB API是连接到CouchDB实例的主要方法。使用HTTP发出请求,请求用于从数据库请求信息、存储新数据以及对存储在文档中的信息执行视图和格式化。
对API的请求可以根据您正在访问的CouchDB系统的不同区域以及用于发送请求的HTTP方法进行分类。不同的方法意味着不同的操作,例如从数据库检索信息通常由 GET
操作,而更新由 POST
或 PUT
请求。必须为不同方法提供的信息之间存在一些差异。有关基本HTTP方法和请求结构的指南,请参阅 请求格式和响应 .
对于几乎所有的操作,提交的数据和返回的数据结构都是在JavaScript对象表示法(JSON)对象中定义的。中提供了有关JSON的内容和数据类型的基本信息 JSON基础知识 .
使用标准HTTP状态代码报告访问CouchDB API时的错误。中提供了CouchDB返回的泛型代码的指南 状态代码HTTP .
当访问couchdbapi的特定区域时,将提供关于HTTP方法和请求、JSON结构和错误代码的特定信息和示例。
1.1.1. 请求格式和响应¶
CouchDB支持以下HTTP请求方法:
GET
请求指定的项。与普通的HTTP请求一样,URL的格式定义了返回的内容。使用CouchDB,可以包括静态项、数据库文档、配置和统计信息。在大多数情况下,信息以JSON文档的形式返回。
HEAD
这个
HEAD
方法来获取GET
没有响应主体的请求。POST
上传数据。在CouchDB内
POST
用于设置值,包括上载文档、设置文档值和启动某些管理命令。PUT
用于放置指定的资源。在CouchDB
PUT
用于创建新对象,包括数据库、文档、视图和设计文档。DELETE
删除指定的资源,包括文档、视图和设计文档。
COPY
可用于复制文档和对象的特殊方法。
如果不支持指定类型的请求,则不支持该类型 405 - Method Not Allowed
将返回,列出支持的HTTP方法。例如:
{
"error":"method_not_allowed",
"reason":"Only GET,HEAD allowed"
}
1.1.2. HTTP头处理模块¶
因为CouchDB使用HTTP进行所有通信,所以您需要确保提供了正确的HTTP报头(并在检索时进行处理),以便获得正确的格式和编码。不同的环境和客户机对这些HTTP报头(尤其是不存在时)的效果会有或多或少的严格限制。如果可能,你应该尽可能具体。
1.1.2.1. 请求标头¶
Accept
指定要由服务器返回的可接受数据类型的列表(即客户端可以接受/理解的数据类型)。格式应该是一个或多个MIME类型的列表,用冒号分隔。
对于大多数请求,定义应该是针对JSON数据的 (
application/json
). 对于附件,可以显式指定MIME类型,也可以使用*/*
指定支持所有文件类型。如果Accept
未提供标头,则*/*
假设为MIME类型(即客户端接受所有格式)。使用
Accept
不需要CouchDB的in查询,但强烈建议使用它,因为它有助于确保客户端可以处理返回的数据。如果使用
Accept
头,CouchDB将使用Content-type
返回了标题字段。例如,如果您明确请求application/json
在Accept
对于请求,返回的HTTP头将使用返回的Content-type
字段。例如,在发送没有显式
Accept
标题,或指定时*/*
:GET /recipes HTTP/1.1 Host: couchdb:5984 Accept: */*
返回的标题是:
HTTP/1.1 200 OK Server: CouchDB (Erlang/OTP) Date: Thu, 13 Jan 2011 13:39:34 GMT Content-Type: text/plain;charset=utf-8 Content-Length: 227 Cache-Control: must-revalidate
注解
返回的内容类型为
text/plain
即使请求返回的信息是JSON格式的。显式指定
Accept
标题:GET /recipes HTTP/1.1 Host: couchdb:5984 Accept: application/json
返回的头包括
application/json
内容类型:HTTP/1.1 200 OK Server: CouchDB (Erlang/OTP) Date: Thu, 13 Jan 2013 13:40:11 GMT Content-Type: application/json Content-Length: 227 Cache-Control: must-revalidate
Content-type
指定请求中提供的信息的内容类型。规范使用MIME类型规范。对于大多数请求,这将是JSON (
application/json
). 对于某些设置,MIME类型将是纯文本。上传附件时,它应该是附件或二进制文件对应的MIME类型 (application/octet-stream
)使用的
Content-type
强烈建议您提出要求。
1.1.2.2. 响应头¶
服务器在发回内容时返回响应头,并包含许多不同的头字段,其中许多是标准的HTTP响应头,对CouchDB操作没有意义。下面列出了对CouchDB很重要的响应头列表。
Cache-control
cache-controlhttp响应头为客户机缓存机制提供了一个关于如何处理返回信息的建议。CouchDB通常返回
must-revalidate
,表示如果可能,应重新验证该信息。这用于确保正确更新内容的动态特性。Content-length
返回内容的长度(以字节为单位)。
Content-type
指定返回数据的MIME类型。对于大多数请求,返回的MIME类型是
text/plain
. 所有文本都是用Unicode(UTF-8)编码的,这在返回的Content-type
作为text/plain;charset=utf-8
.Etag
这个
Etag
HTTP头字段用于显示文档或视图的修订。etag已分配给map/reduce组(单个设计文档中的视图集合)。对这些视图的任何索引的任何更改都将为单个设计文档中的所有视图url生成一个新的ETag,即使该特定视图的结果没有更改。
各
_view
URL有它自己的ETag,只有在对影响该索引的数据库进行更改时才会更新它。如果该特定视图的索引没有更改,则该视图将保留原始的ETag头(因此会发回)304 - Not Modified
更多的时候)。Transfer-Encoding
如果响应使用编码,则在此头字段中指定。
Transfer-Encoding: chunked
表示响应是分部分发送的,这种方法称为 chunked transfer encoding . 当CouchDB事先不知道它将要发送的数据的大小时(例如 changes feed )X-CouchDB-Body-Time
接收请求正文所用的时间(毫秒)。
当请求中包含正文内容时可用。
X-Couch-Request-ID
请求的唯一标识符。
1.1.3. JSON基础知识¶
对CouchDB的大多数请求和响应都使用JavaScript对象表示法(JSON)来格式化数据和响应的内容和结构。
使用JSON是因为它是在web浏览器中处理数据的最简单和最简单的解决方案,因为JSON结构可以在web浏览器环境中作为JavaScript对象进行计算和使用。JSON还集成了CouchDB中使用的服务器端JavaScript。
JSON支持JavaScript支持的基本类型,这些基本类型包括:
数组-括在方括号中的值列表。例如:
["one", "two", "three"]
布尔值-a
true
或false
价值观。你可以直接使用这些字符串。例如:{ "value": true}
数字-整数或浮点数。
对象-一组键/值对(即关联数组或哈希)。键必须是字符串,但值可以是任何受支持的JSON值。例如:
{ "servings" : 4, "subtitle" : "Easy to make in advance, and then cook when ready", "cooktime" : 60, "title" : "Chicken Coriander" }
在CouchDB中,JSON对象用于表示各种结构,包括主CouchDB文档。
字符串-应该用双引号括起来,并支持Unicode字符和反斜杠转义。例如:
"A String"
支持通过将JSON解析为JavaScript对象 JSON.parse()
函数,或通过各种库来执行将内容解析为JavaScript对象的函数。用于解析和生成JSON的库有很多种语言,包括Perl、Python、Ruby、Erlang等。
警告
应该注意确保您的JSON结构是有效的,无效的结构将导致CouchDB返回一个HTTP状态代码500(服务器错误)。
1.1.3.1. 处理编号¶
不熟悉计算机处理数字的开发人员和用户经常会遇到意外情况,因为他们认为以JSON格式存储的数字不一定会返回与逐个字符比较相同的数字。
JSON中定义的包含小数点或指数的任何数字都将通过erlangvm的“double”数据类型的思想进行传递。在视图中使用的任何数字都将通过视图服务器的数字概念(常见的JavaScript案例意味着,由于JavaScript对数字的定义,偶数整数都会通过double)。
考虑一下我们写给CouchDB的文档:
{
"_id":"30b3b38cdbd9e3a587de9b8122000cff",
"number": 1.1
}
现在让我们从CouchDB读回该文档:
{
"_id":"30b3b38cdbd9e3a587de9b8122000cff",
"_rev":"1-f065cee7c3fd93aa50f6c97acde93030",
"number":1.1000000000000000888
}
所发生的是CouchDB正在改变解码结果的文本表示,并将其转换为某种数字格式。在大多数情况下,这是一个 IEEE 754 双精度浮点数,几乎所有其他语言都使用这个数字。
Erlang与其他语言有一点不同的是,它不尝试以最短的字符数打印结果输出。例如,这就是我们建立这种关系的原因:
ejson:encode(ejson:decode(<<"1.1">>)).
<<"1.1000000000000000888">>
令人困惑的是,这两种格式在内部解码成相同的IEEE-754表示。更重要的是,当它通过我们所知道的所有主要解析器时,它将被解码成一个相当接近的表示。
虽然我们只讨论了文本表示形式发生变化的情况,但另一个重要的情况是输入值包含的精度超过了在double中实际表示的精度。(如果您不接受数字是以双精度存储的,您可能会争辩说,这种情况实际上是在“丢失”数据)。
下面是作者机器上两个更常见的JSON库的日志:
位于CouchDB sha 168a663b的Ejson(CouchDB的当前解析器):
$ ./utils/run -i
Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:2:2] [rq:2]
[async-threads:4] [hipe] [kernel-poll:true]
Eshell V5.8.5 (abort with ^G)
1> ejson:encode(ejson:decode(<<"1.01234567890123456789012345678901234567890">>)).
<<"1.0123456789012346135">>
2> F = ejson:encode(ejson:decode(<<"1.01234567890123456789012345678901234567890">>)).
<<"1.0123456789012346135">>
3> ejson:encode(ejson:decode(F)).
<<"1.0123456789012346135">>
节点::
$ node -v
v0.6.15
$ node
JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
'1.0123456789012346'
var f = JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
undefined
JSON.stringify(JSON.parse(f))
'1.0123456789012346'
Python ::
$ python
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
import json
json.dumps(json.loads("1.01234567890123456789012345678901234567890"))
'1.0123456789012346'
f = json.dumps(json.loads("1.01234567890123456789012345678901234567890"))
json.dumps(json.loads(f))
'1.0123456789012346'
红宝石::
$ irb --version
irb 0.9.5(05/04/13)
require 'JSON'
=> true
JSON.dump(JSON.load("[1.01234567890123456789012345678901234567890]"))
=> "[1.01234567890123]"
f = JSON.dump(JSON.load("[1.01234567890123456789012345678901234567890]"))
=> "[1.01234567890123]"
JSON.dump(JSON.load(f))
=> "[1.01234567890123]"
注解
在Ruby上,它需要一个顶级的对象或数组,所以我只包装了这个值。显然,它不会影响解析数字的结果。
Spidermonkey::
$ js -h 2>&1 | head -n 1
JavaScript-C 1.8.5 2011-03-31
$ js
js> JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
"1.0123456789012346"
js> var f = JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
js> JSON.stringify(JSON.parse(f))
"1.0123456789012346"
正如您所看到的,它们的行为基本相同,除了Ruby实际上似乎比其他库失去了一些精度。
敏锐的观察者会注意到ejson(CouchDB JSON库)报告了额外的三位数。虽然它很容易认为这是由于一些内部差异,但它只是上面描述的1.1输入的一个更具体的情况。
这里要注意的一点是,double只能保存有限数量的值。我们要做的是生成一个字符串,当它通过“标准”浮点解析算法(即, strtod
)会在内存中产生与我们开始时相同的位模式。或者,稍有不同,JSON序列化数字中的字节被选择为引用一个double可以表示的单个特定值。
重要的一点是,我们是从一个无限集映射到一个有限集。一个简单的方法就是思考一下:
1.0 == 1.00 == 1.000 = 1.(infinite zeros)
显然,计算机不能容纳无限字节,所以我们必须将无限大的集合抽取成一个可以简洁表示的有限集合。
其他JSON库正在玩的游戏只是:
“要为double选择此特定值,我必须使用几个字符”
而且这个游戏有很多微妙的细节,如果不花大量的精力,很难在C语言中复制(Python花了一年多的时间才把它与那些自动运行在许多不同架构上的奇特构建系统进行分类)。
希望我们已经证明CouchDB并没有通过改变输入来做任何“奇怪”的事情。它的行为与任何其他常见的JSON库相同,只是打印输出不太好。
另一方面,如果你真的处于这样一个位置,IEEE-754双精度对你的数字来说不是一个令人满意的数据类型,那么答案就是不要通过这个表示传递你的数字。在JSON中,这是通过将它们编码为字符串或使用整数类型来实现的(尽管如果使用的平台的整数表示形式与普通的JavaScript不同,那么整数类型仍然会咬到你)。
可以很容易地找到更多信息,包括 Floating Point Guide 和 David Goldberg's Reference .
另外,如果有人真的对改变这种行为感兴趣,我们会全神贯注地倾听 jiffy (理论上,当我们开始更新构建系统时,它将取代ejson)。我们寻找灵感的地方是TCL和Python。如果你知道一个不错的浮动打印算法的实现给我们一个叫嚣。
1.1.4. 状态代码HTTP¶
当CouchDB的接口通过HTTP工作时,使用HTTP状态代码号和响应数据体中的相应数据的组合来报告错误代码和状态。
CouchDB返回的错误代码列表以及相关错误的一般描述如下。特定请求类型的不同状态代码的含义在相应的API调用引用中提供。
200 - OK
请求已成功完成。
201 - Created
文档创建成功。
202 - Accepted
请求已被接受,但相应的操作可能尚未完成。这用于后台操作,例如数据库压缩。
304 - Not Modified
请求的附加内容尚未修改。它与ETag系统一起用于标识返回信息的版本。
400 - Bad Request
错误的请求结构。此错误可能表示请求URL、路径或标头有错误。所提供的MD5哈希和内容之间的差异也会触发此错误,因为这可能表明消息已损坏。
401 - Unauthorized
使用提供的授权无法使用请求的项目,或者未提供授权。
403 - Forbidden
禁止请求的项目或操作。
404 - Not Found
找不到请求的内容。内容将包括进一步的信息,如果可用的话,作为JSON对象。结构将包含两个键,
error
和reason
. 例如:{"error":"not_found","reason":"no_db_file"}
405 - Method Not Allowed
对请求的URL使用无效的HTTP请求类型发出了请求。例如,您请求
PUT
当APOST
是必需的。这种类型的错误也可以由无效的URL字符串触发。406 - Not Acceptable
服务器不支持请求的内容类型。
409 - Conflict
请求导致更新冲突。
412 - Precondition Failed
来自客户端的请求标头与服务器的功能不匹配。
413 - Request Entity Too Large
单据超出配置的
couchdb/max_document_size
值或整个请求超过chttpd/max_http_request_size
价值。415 - Unsupported Media Type
支持的内容类型以及请求或提交的信息的内容类型表明不支持该内容类型。
416 - Requested Range Not Satisfiable
服务器无法满足请求标头中指定的范围。
417 - Expectation Failed
批量发送文档时,批量加载操作失败。
500 - Internal Server Error
请求无效,原因可能是提供的JSON无效,或者请求中提供了无效信息。