mongoDB

  • shell就是可以接受用户输入命令的程序。将shell分为两类:命令行与图形界面。命令行壳层提供一个命令行界面(CLI);而图形壳层提供一个图形用户界面(GUI)。

  • mongodb是一个面向文档(document-oriented)的数据库,而不是关系型数据库。不采用关系模型是为了获得更好的扩展性。

  • 没有预定义模式(predefined schema);文档的键key和值value不再是固定的类型和大小。

  • 扩展数据库:纵向扩展scale up和横向扩展scale out。前者是用更好的服务器。后者是将数据分散到更多机器上。mongodb使用横向扩展。

基础知识

  • 文档是mongodb中数据的基本单元,类似于关系数据库管理找那个的行。

  • 集合collection可以看做是一个拥有动态模式dynamic schema的表。

  • mongodb的一个实例可以拥有多个相互独立的数据库,每个数据库都拥有自己的集合。

  • 每个文档都有一个特殊的键“_id”,这个键在文档所属的集合是唯一的。

  • mongodb自带了一个简单但功能强大的JavaScript shell,用于管理mongodb的实例或数据操作。

##文档

  • 文档就是键值对的一个有序集。大多数编程语言都有相同的数据结构。映射map、散列hash、字典dictionnary。

  • 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。键不能包含\0(空字符),这个字符用于表示键的结尾。.和$具有特殊意义。

  • mongodb区分类型和大小写

    1
    2
    3
    4
    5
    6
    // 类型
    {"foo": 3}
    {"foo": "3"}
    // 大小写
    {"foo": 3}
    {"Foo": 3}
  • mongodb文档中不能有重复的键。

  • 文档中的键值对是有序的:

    1
    2
    3
    // 键值对顺序
    {"x": 1, "y": 2}
    {"y": 2, "x": 1}

集合

集合就是一组文档,文档可以比喻成行,集合则相当于一张表。

动态模式

集合是动态模式的,也就是说集合中的文档可以是各式各样的,可以防止任何文档。为了提高维护性和高效,需要把相关类型的文档组织在一起,尽管mongodb对此没有强制要求。

命名

集合使用名称进行标识。集合可以是任意utf-8字符串。除了某些例外情况。

组织集合的一种惯例是使用”.”分隔不同命名空间的子集合。

数据库

  • 在mongodb中,多个文档组成集合,多个集合组成数据库。多个数据库组成mongodb实例。

  • 数据库也通过名称来标识,满足条件的utf-8字符串。类似集合。

  • 数据库最终会变成文件系统里的文件,而数据库名就是响应的文件名,这是数据库名有限制的原因

  • 把数据库名添加到集合名前得到集合的完全限定名,即明明空间namespace。例如,要使用cms数据库中blog.posts集合,这个集合的命名空间就是cms.blog.posts

启动mongodb

  1. mongod –dbpath “dir”

shell

  1. mongodb自带JavaScript shell,可以在shell中使用命令行和mongodb实例交互。启动shell mongo

  2. shell是一个功能完备的js解释器,可以运行任意JavaScript程序。

  3. shell会连接到mongodb服务器的test数据库,并将数据库连接赋值给全局变量db,这个变量是通过shell访问mongodb的主要入口点。

  4. 查看当前指向哪个数据库,使用db命令:db

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

  6. shell还包含一些非js语法的扩展。

  7. 切换数据库 : use database

    shell 中的基本操作

  8. 4个基本操作:创建、读取、更新、删除(CRUD操作)

创建

创建:insert(doc)函数将一个文档添加到集合中。

读取

find(),findOne()方法可以用于查询集合里的文档。后者只查看一个文档。接收一个查询文档作为限定条件,这样就可以查询符合一定条件的文档。

更新

使用update修改,update介绍至少两个参数:限定条件(匹配待更新的文档),第二个是新的文档。比如,我们需要为文章添加一个评论功能,就增加一个新的键,用于保存评论数组。

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

删除

使用remove方法可将文档从数据库中永久删除。如果没有使用任何参数,它会将集合内的所有文档全部删除。它可以接受一个作为限定条件的文档作为参数。例如:

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

数据类型

基本数据类型

  1. mongoDB的文档与js对象相近,可以认为它类似于json。但json只支持null、boolean,number,string,array,object类型,表达能力有一定缺陷。

  2. mongodb在保留json键值对特性的基础上添加了其他数据类型。
    null,表示空值或不存在。
    布尔型,true,false
    数值,shell默认使用64位浮点型数值。对于整数型可以使用NumberInt类(4字节带符号)\NumberLong(8字节带符号整数)
    字符串,UTF-8字符串都可以表示为字符串类型
    日期,**日期被存储为自新纪元以来经过的毫秒数,不存储时区。
    正则表达式,
    ……

日期

创建日期对象,应该使用new Date(),而非Date()。

数组

数组是一组值,可以作为有序对象(列表,栈或者队列),也能作为无序对象来操作。

内嵌文档

文档可以作为键的值,这样的文档就是内嵌文档,使用内嵌文档,可以使数据组织方式更加自然。

_id和objectID

  1. 在集合里面,每一个文档都有唯一的_id,确保集合里面每个文档都能被唯一标示。

  2. ObjectId是_id的默认类型

  3. 自动生成_id,如果插入文档时没有_id键,则系统会自动创建一个。

使用mongoDB shell

  1. 可以将shell连接到任何mongoDB实例。在启动shell时指定机器名和端口名,就可以连接到一台不同的机器。mongo some-host:30000/myDB

  2. 启动mongo shell 时不连接任何mongod,通过 mongo --nodb启动shell。启动之后可以在需要的时候运行命令得到想要的mongod

    1
    2
    conn = new Mongo("some-host:27017");
    db = conn.getDB("myDB");

shell tips

  1. mongo就是一个简化的JavaScript shell,用JavaScript语法即可得到解析。对于mongoDB特有的功能,shell内置了帮助文档,可以使用help命令查看。help

  2. 如果想知道一个函数的源码可以直接在shell中输入函数名。db.coll.method

使用shell执行脚本

  1. mongo file.js

  2. load(file.js),相对路径,绝对路径【注意加载的js文件有些地方如果无法解析则会出错,比如console在mongo中是无法解析的】

  3. 在脚本中可以访问db变量,以及其他全局变量,但是shell辅助函数比如use dbName,不可以在文件中使用

创建.mongorc.js

  1. .mongorc.js文件会在启动shell时自动运行。

  2. 这个文件最常用的是移除那些比较危险的shell辅助函数。

  3. 禁止加载 ‘.mongorc.js’

    定制shell提示

编辑复合变量

集合命名注意事项

  1. 使用db.collectionName获取一个集合的内容。

  2. 为了访问某些无效的JS属性名称,需要用db.getCollection("version")来访问响应的集合。

  3. 使用[]也可以访问无效属性名称的集合。

创建、更新和删除文档

插入并保存文档

插入是向MongoDB中添加数据的基本方法。可以使用insert方法向目标集合插入一个文档。

  1. 批量插入:使用batchInsert函数实现批量插入,它与insert函数非常像,只是它几首的是一个文档数组作为参数

  2. 执行批量插入的时候有一个文档插入失败,那么文档之前的所有文档都会成功插入到集合汇总,而这个文档以及之后的所有文档全部插入失败

  3. 插入检验:mongodb只对数据进行最基本的检查:检查文档的基本结构,如果没有”_id”字段,就自动增加一个。

删除文档

  1. 要删除一些数据:db.coll.remove({opt}),删除数据是永久性的,无法撤销和恢复

  2. 删除速度:如果要清空整个集合,使用drop()直接删除集合会更快。

更新文档

  1. 使用update方法来更新数据。update有两个参数,一个是查询文档,也就是需要更新的目标文档,另一个是修改器文档,也就是要对找打的文档进行哪些修改。

  2. 文档替换:最简单的更新就是用一个新文档完全替换匹配的文档。【为了确保更新时具有相同的_id,最好还是用_id键来匹配】

  3. 使用修改器:通常文档只会有一部分要更新,可以使用原子性的更新修改器(update modifier),指定对文档中的某些字段进行更新。

  4. "$inc" : {}

  5. $set : {}

  6. 数组修改器

  7. 把数组当做数据集使用

  8. 修改器速度

  9. upsert,是一种特殊的更新,要是没有找到符合更新条件的文档,就会以这个条件和更新文档为基础创建一个新的文档。只需要在update的参数中添加一个true。

  10. save()是一个shell 函数,如果文档不存在,自动创建文档,如果文档存在,就更新这个文档。

  11. 更新多个文档

  12. 返回被更新的文档

  13. 写入安全机制

查询

find()

mongodb中使用find进行查询。查询就是返回一个集合中文档的自己,自己范围是0个文档到整个集合。**find()的第一个参数决定了要返回哪些文档,这个参数是一个文档,用于指定查询条件。默认是{}。db.c.find(),如此将批量返回集合c中的所有文档。

指定需要返回的键

有时候并不需要将文档中所有键/值对都返回,遇到这种情况,可以通过第二个参数来指定想要的键。
db.daily.find({"age":20}, {"username": 1})
默认情况总是返回 _id键。1代表需要返回这个键,0则代表不需要返回这个键。

查询条件

  1. 比较操作符:$lt, $lte, $gt, $gte, $ne分别 对应<, <=, >, >=, !=
    db.users.find({"age": {"$gte": 18, "$lte": 30}})

OR查询

  1. 有两种方式进行OR查询,$in可以用来查询一个键的多个值,$or更通用一些,可以在多个键中查询任意的给定值。

  2. 当一个键需要与多个值进行匹配的话,就需要用$in操作符,配合使用一个条件数组。
    db.users.find({"registered": {"$in": [13, 30,46]}})

  3. $nin返回与数组所有条件都不匹配的文档。

  4. $or接收一个包含所有可能条件的数组作为参数。
    db.user.find({"$or": [{"age":20}, {"height": "50kg"}]})

$not

$not是元条件句,可以用在任何其他条件之上。
db.users.find({"id_num": {"$not": {"$mod": [5, 1]}}})

条件语义

条件语句是内层文档的键,而修改器则是外层文档的键。

特定类型的查询

  1. null,能匹配自身以及不包含这个键的文档

  2. 正则表达式:mongodb使用perl兼容的正则表达式PCRE库来匹配正则表达式。

  3. 查询数组元素和查询标量值是一样的。
    有以下操作符:
    $all
    $size
    $slice:返回某个键匹配的数组元素的一个子集{"comments:" {"$slice": 10}}

  4. 查询内嵌文档:查询整个文档,或者只针对其键值对进行查询。

$where查询

在其他查询方法都走不通的时候,就要考虑$where子句。用它可以在查询中执行任意的JavaScript。最常见的应用就是比较文档中的两个键是否相等。只有迫不得已再用。

服务器脚本

服务器端JS很容易受到注入攻击。可以指定在运行mongod时指定--noscripting,完全关闭JS的执行。

游标

数据库使用游标返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效的控制。可以限制结果的数量、略过部分结果……还有一些强大的操作。

  1. 最常用的查询选项就是限制返回结果的数量、忽略一定数量的结果以及排序。limit\skip\sort

  2. 比较顺序:mongoDB处理不同类型的数据是有一定顺序的。

  3. 避免使用skip略过大量结果

  4. 高级查询选项

数据库命令

特殊的查询类型:数据库命令database command。文档的创建、更新、删除以及查询这些都是数据库命令的使用范畴。

  1. 删除集合使用drop数据库命令完成db.runCommand({"drop": "test"}),这就相当于使用shell辅助函数,db.test.drop()

  2. 在shell中运行db.listCommands()可以看到所有的数据库命令

数据库命令原理

  1. 数据库命令总会返回一个ok键的文档,如果ok键时true,则成功,否则就是失败,并且有一个额外的键“errmsg”。

索引