mongodb笔记(二) 入门

Contents

  1. 1. 文档
  2. 2. 集合
    1. 2.1. 无模式
    2. 2.2. 命名
    3. 2.3. 子集合
  3. 3. 数据库
    1. 3.1. 命名
  4. 4. MongoDB shell
    1. 4.1. 基本操作
    2. 4.2. 技巧
  5. 5. 数据类型
    1. 5.1. 基本数据类型

文档

多个键/值对有序放置在一起便是文档。文档类似于关系数据库中的行,但比行要复杂很多。

  • 文档中键值对是有序的
  • 文档中的值可以是字符串,也可以是其它数据类型。除了少数情况,键可以使用任意UTF-8字符
  • 键不能含有\0,这个字副用来表示键的结尾
  • .,$有特别的意义,通常是保留的
  • _开头的键是保留的
  • mongodb区分类型同时也区分大小写
  • mongodb不能有重复的键

{“one”:”hello”,”one”:”world”} 是非法的

下面几组文档是不同的:

1
2
{"foo":3}
{"foo":"3"}
1
2
{"foo":3}
{"Foo":3}
1
2
{"one":"hello","foo":3}
{"foo":3,"one":"hello"}

集合

集合就是一组文档,类似于关系数据库的表

无模式

集合是没有模式的,一个集合里面的文档可以是各式各样的,例如:

1
2
{"one":"hello"}
{"foo":3}

上面文档不光值类型不同,键也完全不同。但是为了检索,索引更加有效,快捷,有必要创建一个模式把相关文档规整到一起。

命名

  • 不能是空字符串""
  • 不能含有\0
  • 不能以”system.”开头,这是系统集合保留的前缀
  • 不能含有保留字符”$”

子集合

组织集合的一种惯例是使用”.”字符分开的按命名空间划分的子集合。例如blog.posts,blog.authors,这样可以使组织关系更好,也就是说blog这个集合(这里根本不需要存在)及其子集合没有任何关系。

数据库

多个集合可以组成数据库,一个mongodb实例可以承载多个数据库,它们之间可视为完全独立的。

命名

  • 不能是空字符串""
  • 不能含有(空格)、.、$、/、\和\0
  • 应全部小写
  • 最多64字节

数据库名会变成文件系统文件,所以命名会有这些限制

一些数据库是系统保留的,如下

  • admin
    ‘root’数据库,如果把用户加入这个数据库,这个用户将继承所有数据库权限,一些特定的服务器端命令也只能从这个数据库运行,如列出所有数据库或关闭数据库。

  • local
    这个数据库永远不会被复制,可用来存储限于本地单台服务器的任意集合

  • config
    当mongo用于分片设置时,在内部使用,用于保存分片信息。

数据库名放在集合名前,得到的就是集合的完全限定名,即命名空间。如在cms数据库中使用blog.posts集合,这个集合的命名空间就是cms.blog.posts。命名空间长度不应超过121字节,实际应用中应小于100字节。

MongoDB shell

运行mongo会自动连接mongodb服务器。shell是一个完备的JavaScript解释其,可运行任何JavaScript程序。

启动shell会自动连接到test数据库,并将数据库的连接赋值给全局变量db

选择使用的数据库

1
use foobar

查看当前数据库

1
db

可以通过db变量访问其中的集合。db.baz将返回当前数据库的baz集合。

基本操作

  • 创建
    insert函数可以添加一个文档到集合中。

    1
    2
    3
    4
    5
    post = { "title" : "my blog",
    "content" : "my blog post",
    "date": new Date()
    }
    db.blog.insert(post)
  • 读取

    find会返回集合中所有文档,findOne返回一个文档。

    1
    2
    db.blog.find()
    db.blog.findOne()

    两个函数可以接受一些限定条件。使用find自动显示最多20个匹配的文档。

  • 更新

    update接受两个参数,更新文档的限定条件和新的文档。给先前的文章增加评论内容

    1
    2
    post.comments = []
    db.blog.update({title:"my blog"}, post)
  • 删除

    remove用来永久性删除文档,没有参数的话将会删除一个集合内的所有文档,也可以指定限定条件。

    1
    db.blog.remove({title:"my blog"})

技巧

  • 查看帮助文档

    help

    db.help() 查看数据库级别的帮助

    db.foo.help() 查看集合相关帮助

    db.foo.update 可以查看该函数javascript源代码

    通过http://api.mongodb.org/js 查看javascript函数api文档。

  • 蹩脚的集合名

    通过db.集合名 的方式访问集合一般是没有问题的。但是如果集合名恰好是数据库类的属性就有问题了。只有在找不到指定属性时才会将其作为集合返回,,所以db.version将得到属性,而不是集合。
    这种情况下,可以使用getCollection函数访问集合

    1
    db.getCollection("version")

    如果集合名中含有无效javascript字符,这个函数也是很有用的。

    1
    db.getCollection("foo-bar")

    如果不这样,-会被javascript当成减号,
    javascript中,x.y和x[‘y’]是等价的,所以可以通过变量访问子集合。
    可以通过下面方式对blog子集合访问

    1
    2
    3
    4
    var collections = ["posts","comments","authors"]
    for (i in collections){
    doStuff(db.blog[collections[i]]);
    }

数据类型

基本数据类型

  • null

    表示空值或不存在的字段

  • 布尔

    有两个值’true’和’false’

  • 32位整数

    shell中这个类型不可用。javascript仅支持64位浮点数,所以32位整数会被自动转换。

  • 64位整数

    shell中也不支持这个类型,而会使用一个特殊内嵌文档来显示64位整数。

  • 64位浮点数

    shell中的数字都是这种类型

  • 字符串

    utf-8字符串可表示为字符串类型的数据

  • 符号

    shell不支持这种类型。shell将数据库中的符号类型转换成字符串。

  • 对象id

    对象id是文档的12字节的唯一id

  • 日期

    日期类型存储的是从标准纪元开始的毫秒数,不存储时区。

  • 正则表达式

    文档中可以包含正则表达式。采用javascript的正则表达式。

  • 代码

    文档中还可以包含javascript代码

  • 二进制数据

    二进制数据可以由任意字节的串组成。shell中无法使用。

  • 最大值

    BSON包括一个特殊类型,表示可能的最大值。shell中没有这个类型

  • 最小值

    BSON包括一个特殊类型,表示可能的最小值。shell中没有这个类型

  • 未定义

    文档中也可以使用未定义类型(javascript中null和undefined是不同的类型)

  • 数组

    值的集合或列表可以表示成数组

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

    文档可以包含别的文档也可以作为值嵌入到父文档中

    1
    {"x":{"foo":"bar"}}

注意

  • 数字

    javascript只有一种数字类型,mongodb有三种,默认情况下,shell中的数字都会被当做64位双精度浮点数。32位整数都能用64位浮点数表示,64位整数用64位浮点数表示有精度问题。

  • 日期

    创建新的Date对象,通常会调用new Date()而不是Date()。调用构造函数(不带new)实际返回对日期的字符串表示,而不是真正的Date对象。这不是mongodb特性,而是javascript的。日期不存储时区信息,可以把时区信息作为其他键的值存储。

  • 数组

    mongodb可以使用原子更新修改数组中的内容

  • 内嵌文档

    内嵌文档使信息表示更加自然,通常也更高效。但是是反规范化的,会有很多重复内容。

  • _id和ObjectId

    mongodb每个文档必须有一个”_id”键,在每个集合中这个键是唯一的,不同集合中的键可以相同。

    • ObjectId

      _id的默认类型。有12个字节。前四个字节是时间戳,和随后5个字节保证秒级别的唯一性,也保证ObjectId大致按插入顺序排列,同时也隐含了文档创建时间,可以提取出来。接着3个字节是主机唯一标示符,确保不同主机ObjectId不同。接下来两个字节是产生ObjectId的进程标识符,保证并发的多个进程产生ObjectId的唯一,最后3个字节是自动增加的计数器,确保相同进程同一秒产生的ObjectId的唯一性。同一秒最多拥有256的3次方个不同ObjectId

    • 自动生成_id

      插入文档,系统会自动加入_id。但是这样会增加服务器端的开销,能从服务器转移到客户端驱动程序,就应该转移。在客户端生成,驱动程序能够提供更加丰富的API。所以通常在客户端由驱动程序来创建_id