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
- mongod –dbpath “dir”
shell
mongodb自带JavaScript shell,可以在shell中使用命令行和mongodb实例交互。启动shell
mongo
shell是一个功能完备的js解释器,可以运行任意JavaScript程序。
shell会连接到mongodb服务器的test数据库,并将数据库连接赋值给全局变量db,这个变量是通过shell访问mongodb的主要入口点。
查看当前指向哪个数据库,使用db命令:
db
通过db变量可以 访问其中的集合。如db.blog返回当前数据库的blog集合。
shell还包含一些非js语法的扩展。
切换数据库 :
use database
shell 中的基本操作
4个基本操作:创建、读取、更新、删除(CRUD操作)
创建
创建:insert(doc)
函数将一个文档添加到集合中。
读取
find(),findOne()
方法可以用于查询集合里的文档。后者只查看一个文档。接收一个查询文档作为限定条件,这样就可以查询符合一定条件的文档。
更新
使用update
修改,update介绍至少两个参数:限定条件(匹配待更新的文档),第二个是新的文档。比如,我们需要为文章添加一个评论功能,就增加一个新的键,用于保存评论数组。1
2post.comments = [];
db.blog.update({"title": "my blog post"}, post);
删除
使用remove
方法可将文档从数据库中永久删除。如果没有使用任何参数,它会将集合内的所有文档全部删除。它可以接受一个作为限定条件的文档作为参数。例如:1
db.blog.remove({"title": "my blog post"});
数据类型
基本数据类型
mongoDB的文档与js对象相近,可以认为它类似于json。但json只支持null、boolean,number,string,array,object类型,表达能力有一定缺陷。
mongodb在保留json键值对特性的基础上添加了其他数据类型。
null,表示空值或不存在。
布尔型,true,false
数值,shell默认使用64位浮点型数值。对于整数型可以使用NumberInt类(4字节带符号)\NumberLong(8字节带符号整数)
字符串,UTF-8字符串都可以表示为字符串类型
日期,**日期被存储为自新纪元以来经过的毫秒数,不存储时区。
正则表达式,
……
日期
创建日期对象,应该使用new Date(),而非Date()。
数组
数组是一组值,可以作为有序对象(列表,栈或者队列),也能作为无序对象来操作。
内嵌文档
文档可以作为键的值,这样的文档就是内嵌文档,使用内嵌文档,可以使数据组织方式更加自然。
_id和objectID
在集合里面,每一个文档都有唯一的
_id
,确保集合里面每个文档都能被唯一标示。ObjectId是_id的默认类型
自动生成_id,如果插入文档时没有_id键,则系统会自动创建一个。
使用mongoDB shell
可以将shell连接到任何mongoDB实例。在启动shell时指定机器名和端口名,就可以连接到一台不同的机器。
mongo some-host:30000/myDB
启动mongo shell 时不连接任何mongod,通过
mongo --nodb
启动shell。启动之后可以在需要的时候运行命令得到想要的mongod1
2conn = new Mongo("some-host:27017");
db = conn.getDB("myDB");
shell tips
mongo就是一个简化的JavaScript shell,用JavaScript语法即可得到解析。对于mongoDB特有的功能,shell内置了帮助文档,可以使用help命令查看。
help
如果想知道一个函数的源码可以直接在shell中输入函数名。
db.coll.method
使用shell执行脚本
mongo file.js
load(file.js)
,相对路径,绝对路径【注意加载的js文件有些地方如果无法解析则会出错,比如console在mongo中是无法解析的】在脚本中可以访问db变量,以及其他全局变量,但是shell辅助函数比如
use dbName
,不可以在文件中使用
创建.mongorc.js
编辑复合变量
集合命名注意事项
使用db.collectionName获取一个集合的内容。
为了访问某些无效的JS属性名称,需要用
db.getCollection("version")
来访问响应的集合。使用[]也可以访问无效属性名称的集合。
创建、更新和删除文档
插入并保存文档
插入是向MongoDB中添加数据的基本方法。可以使用insert
方法向目标集合插入一个文档。
批量插入:使用
batchInsert
函数实现批量插入,它与insert函数非常像,只是它几首的是一个文档数组作为参数执行批量插入的时候有一个文档插入失败,那么文档之前的所有文档都会成功插入到集合汇总,而这个文档以及之后的所有文档全部插入失败
插入检验:mongodb只对数据进行最基本的检查:检查文档的基本结构,如果没有”_id”字段,就自动增加一个。
删除文档
要删除一些数据:
db.coll.remove({opt})
,删除数据是永久性的,无法撤销和恢复删除速度:如果要清空整个集合,使用
drop()
直接删除集合会更快。
更新文档
使用update方法来更新数据。update有两个参数,一个是查询文档,也就是需要更新的目标文档,另一个是修改器文档,也就是要对找打的文档进行哪些修改。
文档替换:最简单的更新就是用一个新文档完全替换匹配的文档。【为了确保更新时具有相同的_id,最好还是用_id键来匹配】
使用修改器:通常文档只会有一部分要更新,可以使用原子性的更新修改器(update modifier),指定对文档中的某些字段进行更新。
"$inc" : {}
$set : {}
数组修改器
把数组当做数据集使用
修改器速度
upsert,是一种特殊的更新,要是没有找到符合更新条件的文档,就会以这个条件和更新文档为基础创建一个新的文档。只需要在update的参数中添加一个true。
save()
是一个shell 函数,如果文档不存在,自动创建文档,如果文档存在,就更新这个文档。更新多个文档
返回被更新的文档
写入安全机制
查询
find()
mongodb中使用find进行查询。查询就是返回一个集合中文档的自己,自己范围是0个文档到整个集合。**find()的第一个参数决定了要返回哪些文档,这个参数是一个文档,用于指定查询条件。默认是{}。db.c.find()
,如此将批量返回集合c中的所有文档。
指定需要返回的键
有时候并不需要将文档中所有键/值对都返回,遇到这种情况,可以通过第二个参数来指定想要的键。db.daily.find({"age":20}, {"username": 1})
默认情况总是返回 _id键。1代表需要返回这个键,0则代表不需要返回这个键。
查询条件
- 比较操作符:
$lt, $lte, $gt, $gte, $ne
分别 对应<, <=, >, >=, !=db.users.find({"age": {"$gte": 18, "$lte": 30}})
OR查询
有两种方式进行OR查询,
$in
可以用来查询一个键的多个值,$or
更通用一些,可以在多个键中查询任意的给定值。当一个键需要与多个值进行匹配的话,就需要用
$in
操作符,配合使用一个条件数组。db.users.find({"registered": {"$in": [13, 30,46]}})
$nin
返回与数组所有条件都不匹配的文档。$or
接收一个包含所有可能条件的数组作为参数。db.user.find({"$or": [{"age":20}, {"height": "50kg"}]})
$not
$not
是元条件句,可以用在任何其他条件之上。db.users.find({"id_num": {"$not": {"$mod": [5, 1]}}})
条件语义
条件语句是内层文档的键,而修改器则是外层文档的键。
特定类型的查询
null,能匹配自身以及不包含这个键的文档
正则表达式:mongodb使用perl兼容的正则表达式PCRE库来匹配正则表达式。
查询数组元素和查询标量值是一样的。
有以下操作符:$all
$size
$slice
:返回某个键匹配的数组元素的一个子集{"comments:" {"$slice": 10}}
查询内嵌文档:查询整个文档,或者只针对其键值对进行查询。
$where查询
在其他查询方法都走不通的时候,就要考虑$where
子句。用它可以在查询中执行任意的JavaScript。最常见的应用就是比较文档中的两个键是否相等。只有迫不得已再用。
服务器脚本
服务器端JS很容易受到注入攻击。可以指定在运行mongod时指定--noscripting
,完全关闭JS的执行。
游标
数据库使用游标返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效的控制。可以限制结果的数量、略过部分结果……还有一些强大的操作。
最常用的查询选项就是限制返回结果的数量、忽略一定数量的结果以及排序。
limit\skip\sort
比较顺序:mongoDB处理不同类型的数据是有一定顺序的。
避免使用skip略过大量结果
高级查询选项
数据库命令
特殊的查询类型:数据库命令database command。文档的创建、更新、删除以及查询这些都是数据库命令的使用范畴。
删除集合使用
drop
数据库命令完成db.runCommand({"drop": "test"})
,这就相当于使用shell辅助函数,db.test.drop()
在shell中运行db.listCommands()可以看到所有的数据库命令
数据库命令原理
- 数据库命令总会返回一个ok键的文档,如果ok键时true,则成功,否则就是失败,并且有一个额外的键“errmsg”。