面向文档的数据库

面向文档的数据库（Document-oriented database）或文档存储，是用于存储、检索和管理面向文档的信息的一种计算机程序。这里称为文档的是半结构化数据，它是不完全形式的结构化数据，不服从于与关系数据库或其他形式数据表有关联之数据模型的形式结构，然而却包含标签或其他标记，用以在数据内分割语义元素和强制记录和字段的层级，因此它也叫做“自我描述结构”。

## 概述

面向文档的数据库是NoSQL数据库的主要类别之一，且“面向文档的数据库”一词的普及程度也因术语NoSQL的使用而有所增长。XML数据库是针对XML文档做了优化的面向文档的数据库的子类。图数据库与之相似，但其添加了一个连接各文档的“联系”层，以便进行快速遍历。一些搜索引擎（也称为信息检索）系统如Elasticsearch提供了足够的对文档的核心操作从而已经满足了面向文档的数据库的定义。

键-值数据库是NoSQL数据库的另一概念，面向文档的数据库是键-值数据库的子类。它们的差别在于处理数据的方式：在键值数据库中，数据是对数据库不透明的；而面向文档的数据库系统依赖于“文档”的内部结构来获取元数据，数据库引擎使用这些元数据进行更深层次的优化。虽然由于系统中的工具使这一差别不甚明显，但在设计概念上，这种文档存储方式利用了现代程序技术来提供更丰富的体验。现代键-值存储经常包括处理元数据的特征，模糊了它与文档存储之间的界线。

文档数据库与传统的关系数据库差异显著。关系数据库通常将数据存储在相互独立的表中，这些表由程序开发者定义，一个单一的对象可能散布在若干表中。对于一个给定对象，文档数据库将其所有信息存储在数据库内某个单一实例中，并且存储的每一个对象可以不同于任一其它对象。这简化了将对象装载入数据库的过程，通常能消除对对象关系映射等类似方案的需求。文档数据库不同于关系数据库，关系数据库基于了关系模型，而文档数据库采用了半结构化模型，没有在数据和模式（schema）之间的分离，使用的结构的数量依赖于目标用途。在半结构化数据中，属于相同类的实体可有不同的变量和特性，即使它们被分组在一起，并且属性的次序是不重要的。

## 文档

面向文档的数据库中心概念是“文档”这个概念。尽管每个面向文档的数据库实现在这个定义的细节上都有所不同，一般而言，它们都假定文档以某种标准格式或编码来封装和编码数据（或信息）。面向文档的数据库使用的编码包括XML、YAML、JSON和BSON，有的实现还可以存储二进制文档格式如PDF和Microsoft Office文档（MS Word、Excel之类）。

在文档存储中的文档粗略的等价于对象这个编程概念。不要求它们遵守标准模式（schema），也不要求它们都有同样的章节、插槽（slot）、部分（part）或键。一般地说，使用对象的程序有很多不同的对象类型，而这些对象经常有很多可选的字段（field）。每个对象，即使是同类的，也可以看起来非常不同。文档存储类似于此，它们在一个单一存储中允许不同类型的文档，运行在文档中的字段是可选的，并且经常允许它们使用不同的编码系统来编码。例如，下面是一个文档，采用JSON编码：

```javascript
{
    "FirstName": "Bob", 
    "Address": "5 Oak St.", 
    "Hobby": "sailing"
}
```

第二个文档可以采用XML来编码：

```xml
  <contact>
    <firstname>Bob</firstname>
    <lastname>Smith</lastname>
    <phone type="Cell">(123) 555-0178</phone>
    <phone type="Work">(890) 555-0133</phone>
    <address>
      <type>Home</type>
      <street1>123 Back St.</street1>
      <city>Boys</city>
      <state>AR</state>
      <zip>32225</zip>
      <country>US</country>
    </address>
  </contact>
```

这两个文档相互共享一些结构性元素，但每个都有唯一性元素。在文档内部的结构和正文及其他数据通常被称为文档的“内容”，并可以通过通过检索或编辑方法（见下文）来引用。关系数据库中，所有记录包含同样的字段，保留未使用字段为空；不同于关系数据库，在上述例子的这两个文档（记录）中都没有空“字段”。这种方式允许向某些记录增加新信息而不要求在数据库中的所有其他记录共享相同结构。

文档数据典型的提供了关联于文档内容并与之一起存储的额外的元数据。这种元数据还可以与增进数据存储有关，提供组织文档，提供安全性，或其他特定于实现的特性。

### CRUD操作

面向文档数据对文档提供类似于其他数据库的核心操作，尽管术语未完全标准化，大多数实践者将它们认可为CRUD：

- 建立（或插入）
- 检索（或查询、查找、读取或寻找）
- 更新（或编辑）
- 删除（或移除）

### 键

在数据库的文档通过代表这个文档的唯一的“键”来寻址。键是一个简单的标识符（简写为ID），典型的是字符串、URI或路径。键可以用来从数据中检索文档。数据库典型的在键上保有索引来加速文档检索，并且在某些情况下要求用键来把文档建立或插入到数据库中。

### 检索

面向文档数据的另一个定义特征，使之超越可用来检索文档的简单的键到文档查找，就是数据库提供允许用户基于内容（或元数据）来检索文档的API或查询语言。例如，你可能需要一个查询，检索特定字段被设置为特定值的所有文档。可获得的查询API或查询语言的特征的集合，还有查询的预期性能，在不同实现之间有显著差异。类似的，可获得的索引选项和配置的特有集合随着不同实现而有着巨大差异。

文档存储和键-值存储有很大差异。在理论上，在键-值存储中值对于存储是不透明的，它们本质上是黑箱子。它们可以提供类似于文档存储的的查找系统，但是对内容的组织有着更少的理解。文档存储使用在文档中的元数据来分类内容，例如允许它们理解一个数字序列是电话号码，而另一个是邮政编码。这允许它们在这种类型的数据上进行查找，例如，包含555的所有电话号码，但忽略邮编 55555。

### 编辑

文档数据典型的提供某种机制来更新或编辑文档的内容（或元数据），替换要么允许在整个文档上，要么在文档的个别结构片段上。

### 组织

文档数据库实现提供各种方式来组织文档，包括如下概念：

- 收集（Collection）：成组的文档，依赖于具体实现，文档可以被强制存留在一个收集内部，也可以被允许存留在多个收集之内。
- 标签（Tag）和不可见元数据：在文档内容之外的附加数据。
- 目录层级：组织成树状结构的成组文档，典型的基于路径或URI。

有时这些组织概念在它们是逻辑的还是物理的、（比如在磁盘上还是在内存中）、表示等方面有一些变化。

## 实现

名称｜发行商｜许可证｜支持语言｜注释｜RESTful API

AllegroGraph｜Franz, Inc.｜专有｜Java, Python, Common Lisp, Ruby, Scala, .NET, Perl｜数据库平台在一个单一数据内支持文档存储和图数据模型。支持JSON, JSON-LD, RDF, 全文查找, ACID, 二阶段提交, 多主复制, Prolog 和 SPARQL。｜是

ArangoDB｜ArangoDB｜Apache License｜C, .NET, Java, Python, Node.js, PHP, Scala, Go, Ruby, Elixir｜数据库系统以一个数据库和统一的查询语言AQL（ArangoDB 查询语言）支持文档存储以及键/值和图数据模型。｜是

BaseX｜BaseX Team｜BSD License｜Java, XQuery｜支持 XML, JSON 和二进制格式；基于客户/服务器的体系；并发结构化和全文查找及更新。｜是

Caché｜InterSystems 公司｜专有｜Java, C♯, Node.js｜常用于健康, 商务和政府应用。｜是

Cloudant｜Cloudant, Inc.｜专有｜Erlang, Java, Scala, 和C｜基于BigCouch的分布式数据库服务，这家公司对Apache背景的CouchDB计划的开源仿制。使用JSON模型。｜是

Clusterpoint Database｜Clusterpoint Ltd.｜专有，有免费下载｜JavaScript, SQL, PHP, .NET, Java, Python, Node.js, C, C++,｜分布式面向文档XML/JSON数据库平台，有着服从ACID的事务；高可用性数据复制和分片；带有相关性排名的内建全文查找引擎；JS/SQL查询语言；GIS；可获得为每使用付费云数据库或作为一个on-premise免费软件下载。｜是

Couchbase Server｜Couchbase, Inc.｜Apache License｜C, .NET, Java, Python, Node.js, PHP, SQL, Go, Spring Framework, LINQ｜分布式NoSQL文档数据库, JSON模型和基于SQL的查询语言。｜是

CouchDB｜Apache软件基金会｜Apache License｜可以发起HTTP请求的任何语言｜JSON于REST/HTTP上，有着多版本并发控制和有限的ACID特性。对视图和查询使用map和reduce。｜是

CrateDB｜CRATE Technology GmbH｜Apache License｜Java｜对跨越集群的实时分布式查询使用类似SQL语法。基于了Lucene/Elasticsearch生态系统带有对二进制对象（BLOB）的内建支持。｜是

Cosmos DB｜Microsoft｜专有｜.NET, Java, Python, Node.js, JavaScript, SQL｜提供Platform-as-a-Service，是Microsoft Azure的一部分。建造于早期Azure DocumentDB之上并进行了扩展。｜是

DocumentDB｜Amazon Web Services｜专有在线服务｜各种, REST｜完全管理的MongoDB v3.6-兼容数据库服务｜是

Elasticsearch｜Shay Banon｜Apache License｜Java｜JSON, 查找引擎。｜是

eXist｜eXist｜LGPL｜XQuery, Java｜XML在REST/HTTP之上, WebDAV, Lucene全文查找, 二进制数据支持, 验证, 版本控制, 集群, 触发器, URL重写, 收集, ACLS, XQuery更新｜是

Informix｜IBM｜专有, 带有非付费版本｜各种（兼容于 MongoDB API）｜RDBMS 带有 JSON, 复制, 分片和 ACID遵守。｜是

Jackrabbit｜Apache基金会｜Apache License｜Java｜Java Content Repository实现｜未知

Lotus Notes (IBM Lotus Domino)｜IBM｜专有｜LotusScript, Java, Lotus @Formula｜MultiValue｜是

MarkLogic｜MarkLogic 公司｜免费开发者许可证或商业｜Java, JavaScript, Node.js, XQuery, SPARQL, XSLT, C++｜分布式面向文档的数据库，对于 JSON, XML, 和RDF triples。内建全文查找, ACID事务, 高可用性和灾难恢复, 证书安全性。｜是

MongoDB｜MongoDB, Inc｜对DBMS为服务器端公共许可证, 对客户驱动程序为Apache2许可证｜C, C++, C♯, Java, Perl, PHP, Python, Go, Node.js, Ruby, Rust, Scala｜文档数据库带有复制和分片, BSON存储（二进制格式JSON）。｜是

MUMPS 数据库｜未知｜Proprietary 和 Affero GPL｜MUMPS｜常用于健康应用。｜未知

ObjectDatabase++｜Ekky 软件｜专有｜C++, C♯, TScript｜二进制原生C++类结构｜未知

OpenLink Virtuoso｜OpenLink 软件｜GPLv21和专有｜C++, C♯, Java, SPARQL｜中间件和数据库引擎混合｜是

OrientDB｜Orient 技术｜Apache License｜Java｜JSON在HTTP之上, SQL支持, ACID事务｜是

PostgreSQL｜PostgreSQL｜PostgreSQL Free License｜C｜HStore, JSON存储(9.2+), JSON函数(9.3+), HStore2 (9.4+), JSONB (9.4+)｜否

Qizx｜Qualcomm｜专有｜REST, Java, XQuery, XSLT, C, C++, Python｜分布式面向文档XML数据库带有集成的全文查找；支持JSON, 文本和二进制。｜是

RethinkDB｜未知｜对DBMS为GNU AGPL，对客户驱动程序为Apache 2 License｜C++, Python, JavaScript, Ruby, Java｜分布式面向文档JSON数据库带有复制和分片。｜否

SAP HANA｜SAP｜专有｜类SQL语言｜ACID事务支持, 唯JSON｜是

Sedna｜sedna.org｜Apache License｜C++, XQuery｜XML数据库｜否

SimpleDB｜Amazon Web Services｜专有在线服务｜Erlang｜未知

Solr｜Apache｜Apache License｜Java｜查找引擎｜是

TokuMX｜Tokutek｜GNU Affero General Public License｜C++, C♯, Go｜MongoDB带有分形树索引｜未知

### XML数据库实现

大多数XML数据库是面向文档的数据库。

## 外部链接

- DB-Engines Ranking of Document Stores by popularity, updated monthly