MongoDB
中数据的基本单元,很是相似于关系型数据库中的行,但更具备表现力;Collection
能够看做是一个动态模式(Dynamic Schema
)的表;MongoDB
的一个实例能够拥有多个相互独立的数据库 ( Database
),每个数据库都拥有本身的集合;_id
,这个键在文档所属的集合中是惟一的;MongoDB
自带了一个简单但功能强大的 JavaScript Shell
,可用于管理 MongoDB
的实例或数据操做。文档是 MongoDB
的核心概念,文档就是键值对的有序集,下面的便是以 JavaScript
语言表现的一份文档:javascript
{ "greeting" : "Hello, world!" }
在绝大多数状况下,文档的键是字符串(除了少数例外),键可使用任意的UTF-8 字符。java
\0
(空字符),这个字符用于表示键的结尾;.
和 $
具备特殊意义,只能在特定环境下使用,一般这两个字符是被保留的,若是使用不当的话,驱动程序会有提示。MongoDB 不但区分类型,还区分大小写,下面的两个文档是不一样的:正则表达式
{ "foo" : "bar" }
与:mongodb
{ "Foo" : "bar" }
另外一个重要的事项是, MongoDB 的文档不能有重复的键,例如:shell
{ "greeting" : "Hello, world!", "greeting" : "Hello, MongoDB!" }
文档中的键/值对是有序的:数据库
{ "x" : 1, "y" : 2 }
与:express
{ "y" : 2, "x" : 1 }
是不一样的。json
集合就是一组文档。若是将 MongoDB 中的一个文档比喻为关系型数据库中的一行,那么一个集合就至关于一张表。vim
集合是动态模式的,这意味着一个集合里面的文档但是各式各样的,如何下面两个文档就能够出现一个集合里面:数组
{ "greeting" : "Hello, world!" }, { "foo" : 5 }
上面的两个文档,除了值不一样外,键也不一样,可是不建议像上面那样作,一样的文档,咱们通常仍是放在一个特定的集合里面更好,不论是速度、效率仍是结构上来说,都要更好。
集合使用名称进行标识,集合名称能够是知足下列条件的任意 UTF-8 字符串:
""
);\0
字符(空字符),这个字符表示集合名的结束;system.
开头,这是为系统集合保留的前缀,例如: system.users
这个集合保存着数据库的用户信息,而 system.namespaces
集合保存着全部数据库集合的信息;$
,由于某些系统生成的集合中饮食 $
。组织集合的一种惯例是使用 .
分隔不一样命名空间的了集合,好比一个具备博客功能的应用可能包含两个集合,分别是 blog.posts
和 blog.authors
。
在 MongoDB 中,多个文档组成集合,而多个集合能够组成数据库,一个 MongoDB 能够承载我个数据库,每一个数据库拥有 0 个或者多个集合,每一个数据库都有独立的权限,即使是在磁盘上,不一样的数据库也放置在不一样的文件中。
数据库经过名称来标识,这点与集合相似,数据库名能够是知足如下条件的任意 UTF-8 字符串:
""
;/
、\
、.
、"
、*
、<
、>
、:
、|
、?
、$
(一个空格)、\0
(空字符);在这里咱们须要记住一点,数据库名最终会变成文件系统中的文件,而数据库名就是相应的文件名,这是数据库名有如此多限制的缘由。
另外,有一些数据库名是保留的,能够直接访问这些有特殊语言的数据库,以下:
admin:
从身份验证的角度来说,这是 root
数据库,若是有一个用户添加到这个数据库,则这个用户将拥有全部数据库的权限;
local
这个数据库永远都不能够复制,且一台服务器上全部的本地集合均可以存储在这个数据训中;
config
MongoDB 用户分片设置时,分片信息会存储在 config
数据库中。
把数据库名称添加到集合名称前,获得集合的彻底限定名,即 命名空间 namespace
,命名空间的长度不得超过 121 字节,而实际应用中,应该小于100字节。
一般,MongoD 做为网络服务器来运行,客户端可链接到该服务器并执行操做。要安装 MongoDB ,能够从官方网站下载相应的适合你系统的版本(http://www.mongodb.org/downloads)。下载完成以后,解压,并把解压以后获得的文件夹复制或者移到至最终你想安装的目录便可。
我将其安装在了 /Users/pantao/Workspace/MongoDB
这个目录,同时,我将 MongoDB
的 bin
目录加入了PATH
变量中:
vi ~/.bash_profile
加入以下一行:
export PATH="/Users/pantao/Workspace/MongoDB/bin:$PATH"
保存以后,运行:
source ~/.bash_profile
这个时候,我就能够直接在任何地方启动 MongoDB
或者进行相关的数据库操做了,使用 mongod
命名启动服务器:
pantaodeMacBook-Pro:MongoDB pantao$ mongod 2015-04-21T10:00:06.302+0800 I STORAGE [initandlisten] exception in initAndListen: 29 Data directory /data/db not found., terminating 2015-04-21T10:00:06.302+0800 I CONTROL [initandlisten] dbexit: rc: 100
出现上面这个错误是由于 /data/db
目录不存在,若启动时,不指定任何参数, MongoDB 会默认使用 /data/db
目录存储数据,咱们可使用 --dbpath
来指定其它的路径,好比我使用的是下面这样的命令启动的:
mongod --dbpath /Users/pantao/Workspace/MongoDB/db
上面这个是个人工做目录,直接将 MongoDB 的程序和数据库放在一块儿,我方便学习管理。
MongoDB 自带有 JavaScript Shell ,能够Shell 中使用命令行与 MongoDB 实例交互,Shell很是有用,经过它能够执行管理操做,检查运行实例,亦或是作其它尝试。
使用 mongo
命令启动 shell
:
pantaodeMacBook-Pro:MongoDB pantao$ mongo MongoDB shell version: 3.0.2 connecting to: test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user Server has startup warnings: 2015-04-21T10:03:18.997+0800 I CONTROL [initandlisten] 2015-04-21T10:03:18.997+0800 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000 >
启动时, shell
会打印出当前 shell
的版本号,链接到了哪一个库以及一些帮助信息等,这是一个功能完备的 JavaScript
解释器,能够运行任意 JavaScript
程序,好比使用 JavaScript
标准库或者定义以及调用 JavaScript 函数等。
shell
是一个独立的 MongoDB客户端,启动时, shell
会连到 MongoDB 服务器的 test
数据库,并将数据库链接赋值给合局变量 db
,这个变量是经过 shell
访问 MongoDB 的主要入口点,可使用 db
查看当前指向哪一个数据库:
> db test
除了JavaScript语法外,MongoDB 还提供了一些语法糖,以帮助咱们更好的管理数据库,好比:
> use foobar switched to db foobar
这个时候咱们能够看到数据库已经切换到 foobar
数据库了:
> db foobar
在 shell
中查看查看或操做数据,会用到4个基本操做:建立、读取、更新、删除,即 CRUD
操做;
经过 db.createCollection()
函数能够先建立一个集合:
> db.createCollection("blog") { "ok" : 1 }
insert
能够将一个文档添加到集合中:
> post = {"title": "这是一篇文章", "content": "这是文章的内容。","date" : new Date()} { "title" : "这是一篇文章", "content" : "这是文章的内容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
这是一个有效的 MongoDB 文档,因此能够用 insert
方法将其保存到集合中。
> db.blog.insert(post) WriteResult({ "nInserted" : 1 })
接着可使用 find
方法查找这篇文章:
> db.blog.find() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "这是一篇文章", "content" : "这是文章的内容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
能够看到咱们的数据都已经完整的保存下来了,同时,MongoDB 还为咱们自动生成了一个 _id
参数。
find
与 findOne
方法能够用于查询集合里的文档:
> db.blog.findOne() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "这是一篇文章", "content" : "这是文章的内容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
find
与 findOne
能够接受一个查询文档做为限定条件,使用 find
时,shell
会自动显示最多 20 个匹配的文档,也能够获取更多文档。
使用 update
修改博客文章,它至少接受两个参数,第一个是限定条件,第二个是新文档,好比咱们如今要给 post
加上评论列表:
> post.comments = [] [ ]
而后,用新版本的 post
替换标题为 《这是一篇文章》的文章:
> db.blog.update({"title":"这是一篇文章"},post) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.blog.findOne() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "这是一篇文章", "content" : "这是文章的内容。", "date" : ISODate("2015-04-21T02:22:52.899Z"), "comments" : [ ] }
能够看到,comments
已经更新到原来的那个 post
中去了。
使用 remove
能够删除集合中的文档,若没有任何限定参数,它将删除集合中的全部数据,也能够像下面这样,删除标题为《这是一篇文章》的文章:
> db.blog.remove({"title":"这是一篇文章"}) WriteResult({ "nRemoved" : 1 }) > db.blog.find() >
MongoDB
的文档与 JavaScript
中的对象相近,于是能够认为相似于 JavaScript
中的 JSON
,JSON 是一种简单的数据表示方式,仅有 6种数据类型,分别为 null
、bool
、number
、string
、array
和 object
。
MongoDB在保留 JSON 基本键/值对特性的基础上,添加了其它的一些数据类型:
null
用于表示空值或者不存在的字段:
{ "x" : null }
bool
布尔型只有两个值 true
与 false
:
{ "x" : true, "y" : false }
number
数值shell
默认使用 64位浮点型数值,对于整型值,可以使用 NumberInt
类或 NumberLong
类:
{ "pi" : 3.14, "x" : 3, "ni" : NumberInt("3"), "nl" : NumberLong("3") }
string
字符串UTF-8
类型的字符串均可以表示为字符串类型的数据:
{ "x" : "this is a string.", "y" : "这是一个NB的字符串" }
date
日期日期被存储 为自新纪元以来通过的毫秒数,不存储时区:
{ "x" : new Date() }
regular expression
正则表达式在进行查询时,咱们能够直接使用正则表达式做为值,语法与 javascript
的相同:
{ "x" : /foobar/i }
array
数组数据列表或数据集能够表达为数组:
{ "a" : ["x", "y" , "z"] }
object id
对象ID对象ID是一个 12 字节的ID,它是文档的惟一标识:
{ "x" : ObjectId() }
object id
以如下方式生成:
|0|1|2|3|4|5|6|7|8|9|10|11| | 时间戳 | 机器|PID| 计数器 |
hash
);_id
若插入文档时,没有提供 _id
键
object
内嵌文档文档能够嵌套其它文档,被嵌套的文档做为父文档的值:
{ "o" : { "name" : "child object" } }
binary data
二进制数据任意字节的字符串,它不直直接在 shell
中使用,若是要将非 utf-8
字符保存到数据库中,二进制数据是惟一的实现方式。
javascript
代码查询和文档中能够包括作生意 JavaScript 代码:
{ "script" : function() { /* code goes here */ } }
timestamps
时间戳不一样于 Date
类型的时间戳值,它是一个 64位长度的值,它是:
time_t
值,(Unix 时间戳)除了像前面那样使用 shell
链接数据库外,咱们还能够在链接数据时指定服务器地址、端口号以及数据名等参数,好比:
mongo mongo-db.xingzhewujiang.com:30000/ahaInsight
启动时,可让 mongo shell
不链接任何的 mongod
,能够经过 --nodb
参数:
mongo --nodb
启动以后,咱们能够在须要时执行 new Mongo(hostname)
命令就能够链接到想要链接的 mongod
了:
> conn = new Mongo("host.name:30000") connection to host.name:30000 > db = conn.getDB("dbname") dbname
在使用 shell
的过程当中,还能够随时使用 help
命令查看帮助:
help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
除了交互式的使用 shell
外,咱们还能够将命令保存在一个文件中,好比 script.js
,而后使用 mongo
命令直接执行它们,一次能够传入多个文件名,mongo shell
会依次执行传入的脚本,而后退出:
mongo script.js script1.js
若是但愿指定主机和端口来运行上面的脚本,还能够这样作:
mongo --quiet host.name:30000/dbname script.js script1.js
--quiet
可让 mongo shell
不打印 MongoDB shell version...
这样的提示信息。
在交互式的命令行中,还可使用 load()
函数加载并运行脚本:
> load("script.js") i am a string printed by script.js >
知道这个以后,咱们能够把一些能用的函数保存到一个文件里面,而后再将他们加载进 shell
交互界面里面来:
建立一个名为 connectTo.js
的文件,内容以下:
javascript/** * 连接到指定的数据库,而后将 db 指向这个连接 */ var connectTo = function(port, dbname) { if (!port) { port = 27017; } if (!dbname) { dbname = "test" } db = connect("localhost:" + port + "/" + dbname) return db }
而后咱们进入 shell
:
bash> typeof connectTo undefined > load("connectTo.js") true > typeof connectTo function >
咱们可使用脚本让能用的管理和任务自动化,好比,咱们想在每一次 shell
启用时,都加载上面定义的那个函数,这个时候咱们能够用到一个名为 .mongorc.js
的文件。
在本身的家目录中(不一样的系统都不同),新建一个名为 .mongorc.js
的文件,而后写入下面这些内容:
print("你好,我来自 .mongorc.js 文件")
而后,从新进入 shell
:
mongo MongoDB shell version: 3.0.2 connecting to: test 你好,我来自 .mongorc.js 文件 >
该文件通常用得最多的就是用于删除一些比较危险的 shell
辅助函数,好比删除数据库、索引等,好比下面这样的:
javascriptvar no = function() { print("Not no my watch."); } // 禁止删除数据库 db.dropDatabase = DB.prototype.dropDatabase = no; // 禁止删除集合 DBCollection.prototype.drop = no; // 禁止删除索引 DBCollection.prototype.dropIndex = no;
shell
默认的提示是一个 >
符号,咱们能够对该符号进行定制,好比最简单的是,在每个提示符前面加上一个当前时间,这样咱们就能够很容易大概的知道,一些须要长时间执行的操做到底用了多久时间了:
javascriptprompt = function() { return (new Date()) + "> "; }
再一次进入 shell
:
bashmongo MongoDB shell version: 3.0.2 connecting to: test Tue Apr 21 2015 13:06:40 GMT+0800 (CST)> Tue Apr 21 2015 13:06:43 GMT+0800 (CST)>db test
另外一个方便的提示是显示当前正在使用的数据库:
javascriptprompt = function() { if (typeof db == 'undefined') { return '(nodb)>'; } // 检查最后使用的数据库操做 try { db.runCommand({getLastError:1}); } catch (e) { print(e); } return db + "> "; }
再一次进入 shell
:
bashmongo MongoDB shell version: 3.0.2 connecting to: test test>
shell
对多行编辑颇有限,若编辑了多行,忽然发现前面有一行有错误,这是不能修改的,可是它提供了一种方法,让你能够在 shell
中很访问的使用外部的第三方编辑器,保存并退出编辑器以后,会对你修改的值进行从新解析,并从新加载回 shell
中,一样使用 .mongorc.js
,在其中加入下面这一行:
EDITOR = "/usr/bin/vim"
而后进入 shell
:编辑一个复杂一点儿的变量:
bashmongo MongoDB shell version: 3.0.2 connecting to: test > var post = { ... title: "这是一篇文章的内容", ... content: "这是一篇文章的标题", ... author: "潘韬" ... } > post { "title" : "这是一篇文章的内容", "content" : "这是一篇文章的标题", "author" : "潘韬" } > edit post > post { "title" : "这是一篇文章的标题", "content" : "这是一篇文章的内容", "author" : "潘韬" } >
绝大多数时候,咱们可使用 db.collectionName
这种方式访问一个数据库中的集合,可是也有例外,好比 db.version
就不能访问到名称为 version
的集合,由于 version
是 db
的一个方法名,能够用来显示当前的数据库版本信息。那么咱们就得使用其它的方法了,好比:
> db.getCollection("version"); test.version
有些时候,咱们的集合里面还可能使用了不少变态的奇怪的名称,好比 &$*%#
,使用 db.&$*%#
是非法的,可是咱们却可使用 db.getCollection("&$*%#")
来获取该集合,一样的,咱们还有一种更加直接的方法,就是相似于JavaScript的数组访问语法,像下面这样:
db["&$*%#"].find()