MongoDB权威指南(第2版)
上QQ阅读APP看书,第一时间看更新

2.2 集合

集合就是一组文档。如果将MongoDB中的一个文档比喻为关系型数据库中的一行,那么一个集合就相当于一张表。

2.2.1 动态模式

集合是动态模式的。这意味着一个集合里面的文档可以是各式各样的。例如,下面两个文档可以存储在同一个集合里面:

        {"greeting" : "Hello, world! "}
        {"foo" : 5}

需要注意的是,上面的文档不光值的类型不同(一个是字符串,一个是整数),它们的键也完全不同。因为集合里面可以放置任何文档,随之而来的一个问题是:还有必要使用多个集合吗?这的确值得思考:既然没有必要区分不同类型文档的模式,为什么还要使用多个集合呢?这里有几个重要的原因。

· 如果把各种各样的文档不加区分地放在同一个集合里,无论对开发者还是对管理员来说都将是噩梦。开发者要么确保每次查询只返回特定类型的文档,要么让执行查询的应用程序来处理所有不同类型的文档。如果查询博客文章时还要剔除含有作者数据的文档,这会带来很大困扰。

· 在一个集合里查询特定类型的文档在速度上也很不划算,分开查询多个集合要快得多。例如,假设集合里面一个名为"type"的字段用于指明文档是skim、whole还是chunky monkey。那么,如果从一个集合中查询这三种类型的文档,速度会很慢。但如果将这三种不同类型的文档拆分为三个不同的集合,每次只需要查询相应的集合,速度快得多。

· 把同种类型的文档放在一个集合里,数据会更加集中。从一个只包含博客文章的集合里查询几篇文章,或者从同时包含文章数据和作者数据的集合里查出几篇文章,相比之下,前者需要的磁盘寻道操作更少。

· 创建索引时,需要使用文档的附加结构(特别是创建唯一索引时)。索引是按照集合来定义的。在一个集合中只放入一种类型的文档,可以更有效地对集合进行索引。

上面这些重要原因促使我们创建一个模式,把相关类型的文档组织在一起,尽管MongoDB对此并没有强制要求。

2.2.2 命名

集合使用名称进行标识。集合名可以是满足下列条件的任意UTF-8字符串。

· 集合名不能是空字符串("")。

· 集合名不能包含\0字符(空字符),这个字符表示集合名的结束。

· 集合名不能以“system.”开头,这是为系统集合保留的前缀。例如,system.users这个集合保存着数据库的用户信息,而system.namespaces集合保存着所有数据库集合的信息。

· 用户创建的集合不能在集合名中包含保留字符’$'。因为某些系统生成的集合中包含$,很多驱动程序确实支持在集合名里包含该字符。除非你要访问这种系统创建的集合,否则不应该在集合名中包含$。

子集合

组织集合的一种惯例是使用“.”分隔不同命名空间的子集合。例如,一个具有博客功能的应用可能包含两个集合,分别是blog.posts和blog.authors。这是为了使组织结构更清晰,这里的blog集合(这个集合甚至不需要存在)跟它的子集合没有任何关系。

虽然子集合没有任何特别的属性,但它们却非常有用,因而很多MongoDB工具都使用了子集合。

· GridFS(一种用于存储大文件的协议)使用子集合来存储文件的元数据,这样就可以与文件内容块很好地隔离开来。(第6章会详细介绍GridFS。)

· 大多数驱动程序都提供了一些语法糖,用于访问指定集合的子集合。例如,在数据库shell中,db.blog代表blog集合,而db.blog.posts代表blog.posts集合。

在MongoDB中,使用子集合来组织数据非常高效,值得推荐。