资讯专栏INFORMATION COLUMN

MongoDB指南---3、MongoDB基础知识-数据类型

aervon / 3021人阅读

摘要:如将构造函数作为函数进行调用即不包括的方式,返回的是日期的字符串表示,而非日期对象。如果不注意这一点,没有始终使用日期构造函数,将得到一堆混乱的日期对象和日期的字符串。关于日期类的完整解释,以及构造函数的参数格式,参见规范节。

上一篇文章:MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端
下一篇文章:MongoDB指南---4、MongoDB基础知识-使用MongoDB Shell

本章开始部分介绍了文档的基本概念,现在你已经会启动、运行MongoDB,也会在shell中进行一些操作了。这一节的内容会更加深入。MongoDB支持将多种数据类型作为文档中的值,下面将一一介绍。

2.6.1 基本数据类型

在概念上,MongoDB的文档与JavaScript中的对象相近,因而可认为它类似于JSON。JSON(http://www.json.org)是一种简单的数据表示方式:其规范仅用一段文字就能描述清楚(其官网证明了这点),且仅包含6种数据类型。这样有很多好处:易于理解、易于解析、易于记忆。然而,从另一方面来说,因为只有null、布尔、数字、字符串、数组和对象这几种数据类型,所以JSON的表达能力有一定的局限。
虽然JSON具备的这些类型已具有很强的表现力,但绝大多数应用(尤其是在与数据库打交道时)都还需要其他一些重要的类型。例如,JSON没有日期类型,这使原本容易的日期处理变得烦人。另外,JSON只有一种数字类型,无法区分浮点数和整数,更别说区分32位和64位数字了。再者,JSON无法表示其他一些通用类型,如正则表达式或函数。
MongoDB在保留JSON基本键/值对特性的基础上,添加了其他一些数据类型。 在不同的编程语言下,这些类型的确切表示有些许差异。下面说明MongoDB支持的其他通用类型,以及如何在文档中使用它们。

null

null用于表示空值或者不存在的字段:

{"x" : null}
布尔型

布尔类型有两个值true和false:

{"x" : true}
数值

shell默认使用64位浮点型数值。因此,以下数值在shell中是很“正常”的:

{"x" : 3.14}

或:

{"x" : 3}

对于整型值,可使用NumberInt类(表示4字节带符号整数)或NumberLong类(表示8字符带符号整数),分别举例如下:

{"x" : NumberInt("3")}
{"x" : NumberLong("3")}
字符串

UTF-8字符串都可表示为字符串类型的数据:

{"x" : "foobar"}
日期

日期被存储为自新纪元以来经过的毫秒数,不存储时区:

{"x" : new Date()} 
正则表达式

查询时,使用正则表达式作为限定条件,语法也与JavaScript的正则表达式语法相同:

{"x" : /foobar/i}
数组

数据列表或数据集可以表示为数组:

{"x" : ["a", "b", "c"]} 
内嵌文档

文档可嵌套其他文档,被嵌套的文档作为父文档的值:

{"x" : {"foo" : "bar"}}
对象id

对象id是一个12字节的ID,是文档的唯一标识。详见2.6.5节。

{"x" : ObjectId()}

还有一些不那么常用,但可能有需要的类型,包括下面这些。

二进制数据

二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要将非UTF-8字符保存到数据库中,二进制数据是唯一的方式。

代码

查询和文档中可以包括任意JavaScript代码:

{"x" : function() { /* ... */ }} 

另外,有几种大多数情况下仅在内部使用(或被其他类型取代)的类型。在本书中,出现这种情况时会特别说明。
关于MongoDB数据格式的更多信息,参考附录B。

2.6.2 日期

在JavaScript中,Date类可以用作MongoDB的日期类型。创建日期对象时,应使用new Date(…),而非Date(…)。如将构造函数(constructor)作为函数进行调用(即不包括new的方式),返回的是日期的字符串表示,而非日期(Date)对象。这个结果与MongoDB无关,是JavaScript的工作机制决定的。如果不注意这一点,没有始终使用日期(Date)构造函数,将得到一堆混乱的日期对象和日期的字符串。由于日期和字符串之间无法匹配,所以执行删除、更新及查询等几乎所有操作时会导致很多问题。
关于JavaScript日期类的完整解释,以及构造函数的参数格式,参见ECMAScript规范15.9节(http://www.ecmascript.org)。
shell根据本地时区设置显示日期对象。然而,数据库中存储的日期仅为新纪元以来的毫秒数,并未存储对应的时区。(当然,可将时区信息存储为另一个键的值)。

2.6.3 数组

数组是一组值,它既能作为有序对象(如列表、栈或队列),也能作为无序对象(如数据集)来操作。
在下面的文档中,"things"这个键的值是一个数组:

{"things" : ["pie", 3.14]}

此例表示,数组可包含不同数据类型的元素(在此,是一个字符串和一个浮点数)。实际上,常规的键/值对支持的所有值都可以作为数组的值,数组中甚至可以套嵌数组。
文档中的数组有个奇妙的特性,就是MongoDB能“理解”其结构,并知道如何“深入”数组内部对其内容进行操作。这样就能使用数组内容对数组进行查询和构建索引了。例如,之前的例子中,MongoDB可以查询出"things"数组中包含3.14这个元素的所有文档。要是经常使用这个查询,可以对"things"创建索引来提高性能。
MongoDB可以使用原子更新对数组内容进行修改,比如深入数组内部将pie改为pi。本书后面还会介绍更多这种操作的例子。

2.6.4 内嵌文档

文档可以作为键的值,这样的文档就是内嵌文档。使用内嵌文档,可以使数据组织方式更加自然,不用非得存成扁平结构的键/值对。
例如,用一个文档来表示一个人,同时还要保存他的地址,可以将地址信息保存在内嵌的"address"文档中:

{
    "name" : "John Doe",
    "address" : {
        "street" : "123 Park Street",
        "city" : "Anytown",
        "state" : "NY"
    }
}  

上面例子中"address"键的值是一个内嵌文档,这个文档有自己的"street"、"city"和"state"键以及对应的值。
同数组一样,MongoDB能够“理解”内嵌文档的结构,并能“深入”其中构建索引、执行查询或者更新。
稍后会深入讨论模式设计,但是从这个简单的例子也可以看得出内嵌文档可以改变处理数据的方式。在关系型数据库中,这个例子中的文档一般会被拆分成两个表中的两个行 (“people”和“address”各一行)。在MongoDB中,就可以直接将地址文档嵌入到人员文档中。使用得当的话,内嵌文档会使信息的表示方式更加自然(通常也会更高效)。
MongoDB这样做的坏处就是会导致更多的数据重复。假设“address”是关系数据库中的一个独立的表,我们需要修正地址中的拼写错误。当我们对“people”和“address”执行连接操作时,使用这个地址的每个人的信息都会得到更新。但是在MongoDB中,则需要对每个人的文档分别修正拼写错误。

2.6.5 _id和ObjectId

MongoDB中存储的文档必须有一个"_id"键。这个键的值可以是任何类型的,默认是个ObjectId对象。在一个集合里面,每个文档都有唯一的"_id",确保集合里面每个文档都能被唯一标识。如果有两个集合的话,两个集合可以都有一个"_id"的值为123,但是每个集合里面只能有一个文档的"_id"值为123。

1. ObjectId

ObjectId是"_id"的默认类型。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。这是 MongoDB采用ObjectId,而不是其他比较常规的做法(比如自动增加的主键)的主要原因,因为在多个服务器上同步自动增加主键值既费力又费时。因为设计MongoDB的初衷就是用作分布式数据库,所以能够在分片环境中生成唯一的标示符非常重要。
ObjectId使用12字节的存储空间,是一个由24个十六进制数字组成的字符串(每个字节可以存储两个十六进制数字)。由于看起来很长,不少人会觉得难以处理。但关键是要知道这个长长的ObjectId是实际存储数据的两倍长。
如果快速连续创建多个ObjectId,会发现每次只有最后几位数字有变化。另外,中间的几位数字也会变化(要是在创建的过程中停顿几秒钟)。这是ObjectId的创建方式导致的。ObjectId的12字节按照如下方式生成:

2. 自动生成_id

前面讲到,如果插入文档时没有"_id"键,系统会自动帮你创建一个。可以由MongoDB服务器来做这件事,但通常会在客户端由驱动程序完成。这一做法非常好地体现了MongoDB的哲学:能交给客户端驱动程序来做的事情就不要交给服务器来做。这种理念背后的原因是,即便是像MongoDB这样扩展性非常好的数据库,扩展应用层也要比扩展数据库层容易得多。将工作交由客户端来处理,就减轻了数据库扩展的负担。

上一篇文章:MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端
下一篇文章:MongoDB指南---4、MongoDB基础知识-使用MongoDB Shell

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43991.html

相关文章

  • MongoDB指南---3MongoDB基础知识-数据类型

    摘要:如将构造函数作为函数进行调用即不包括的方式,返回的是日期的字符串表示,而非日期对象。如果不注意这一点,没有始终使用日期构造函数,将得到一堆混乱的日期对象和日期的字符串。关于日期类的完整解释,以及构造函数的参数格式,参见规范节。 上一篇文章:MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端下一篇文章:MongoDB指南---4、MongoDB基础知识-使用M...

    tunny 评论0 收藏0
  • MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端

    摘要:上一篇文章指南简介下一篇文章指南基础知识数据类型非常强大但很容易上手。把同种类型的文档放在一个集合里,数据会更加集中。命名集合使用名称进行标识。集合名不能是空字符串。简单起见,数据库名应全部小写。 上一篇文章:MongoDB指南---1、MongoDB简介下一篇文章:MongoDB指南---3、MongoDB基础知识-数据类型 MongoDB非常强大但很容易上手。本章会介绍一些Mon...

    SnaiLiu 评论0 收藏0
  • MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端

    摘要:上一篇文章指南简介下一篇文章指南基础知识数据类型非常强大但很容易上手。把同种类型的文档放在一个集合里,数据会更加集中。命名集合使用名称进行标识。集合名不能是空字符串。简单起见,数据库名应全部小写。 上一篇文章:MongoDB指南---1、MongoDB简介下一篇文章:MongoDB指南---3、MongoDB基础知识-数据类型 MongoDB非常强大但很容易上手。本章会介绍一些Mon...

    W4n9Hu1 评论0 收藏0
  • MongoDB指南---5、创建、删除文档

    摘要:例如,假设要删除集合中所有为的人删除数据是永久性的,不能撤销,也不能恢复。删除速度删除文档通常很快,但是如果要清空整个集合,那么使用直接删除集合会更快然后在这个空集合上重建各项索引。上一篇文章指南基础知识使用下一篇文章指南更新文档 上一篇文章:MongoDB指南---4、MongoDB基础知识-使用MongoDB Shell下一篇文章:MongoDB指南---6、更新文档 本章会介绍...

    jas0n 评论0 收藏0
  • MongoDB指南---5、创建、删除文档

    摘要:例如,假设要删除集合中所有为的人删除数据是永久性的,不能撤销,也不能恢复。删除速度删除文档通常很快,但是如果要清空整个集合,那么使用直接删除集合会更快然后在这个空集合上重建各项索引。上一篇文章指南基础知识使用下一篇文章指南更新文档 上一篇文章:MongoDB指南---4、MongoDB基础知识-使用MongoDB Shell下一篇文章:MongoDB指南---6、更新文档 本章会介绍...

    int64 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<