MongoDB权威指南第二版学习笔记二
Posted 冰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB权威指南第二版学习笔记二相关的知识,希望对你有一定的参考价值。
数据类型
MongoDB在保留JSON基本键/值对特性的基础上,添加了其他一些数据类型。
null
null用于表示空值或者不存在的字段:{“x”:null}
布尔型
布尔类型有两个值true和false {“x”:true}
数值
shell默认使用64位浮点型数值。 {“x”:3.14} 或 {“x”:3}
对于整型值,可使用NumberInt类(表示4字节带符号整数)或NumberLong类(表示8字符带符号整数) {“x”:NumberInt(”3”)} {“x”:NumberLong(“3”)}
字符串
utf-8字符串都可以表示为字符串类型的数据: {“x”:”foobar”}
日期
日期被存储为自新世纪以来经过的毫秒数,不存储时区: {“x”:new Date()}
创建日期对象时,应使用 new Date() ,而非Date(),后者返回的是日期的字符串表示,而非日期 Date对象。这个结果与MongoDB无关,是js的工作机制决定的。由于日期和字符串之间无法匹配,所以执行删改查等几乎所有操作时会导致很多问题。
> db.blog.insert({"x":Date()}) WriteResult({ "nInserted" : 1 }) > db.blog.find() { "_id" : ObjectId("584ea42d3bb80d550a5914fe"), "x" : "Mon Dec 12 2016 21:20:45 GMT+0800 (CST)" } > db.blog.insert({"x":new Date()}) WriteResult({ "nInserted" : 1 }) > db.blog.find() { "_id" : ObjectId("584ea42d3bb80d550a5914fe"), "x" : "Mon Dec 12 2016 21:20:45 GMT+0800 (CST)" } { "_id" : ObjectId("584ea4573bb80d550a5914ff"), "x" : ISODate("2016-12-12T13:21:27.361Z") }
正则表达式
查询时,使用正则表达式作为限定条件 {“x”:/foobar/i}
数组
数据列表或数组集可以表示为数组: {“x”:[“a”,”b”,”c”]}
数组是一组值,它既能作为有序对象(如列表、栈或队列),也能作为无序对象(如数据集)来操作。
数组中可包含不同数据类型的元素 {“things”:[“pie”,3.14]} 。只要是常规的键/值对支持的所有值都可以作为数组的值,数组中甚至可以嵌套数组。
内嵌文档
文档可内嵌其他文档,被嵌套的文档作为父文档的值: {“x”:{“foo”,”bar”}}
使用内嵌文档,可以使数据组织更加自然,不用非得存成扁平结构的键/值对。
> post={ ... "user":{ ... "name":"yyb", ... "address":{ ... "street":"123 Park Street", ... "city":"Anytown", ... "state":"NY" ... } ... } ... } { "user" : { "name" : "yyb", "address" : { "street" : "123 Park Street", "city" : "Anytown", "state" : "NY" } } } > db.blog.insert(post) WriteResult({ "nInserted" : 1 }) > db.blog.find() { "_id" : ObjectId("584ea90fce4f8e1bf30ba07d"), "user" : { "name" : "yyb", "address" : { "street" : "123 Park Street", "city" : "Anytown", "state" : "NY" } } }
对象id
对象id是一个12字节的ID,是文档的唯一标识 {“x”:ObjectId()}
MongoDB中存储的文档必须有一个“_id”键。确保集合中的每个文档都能被唯一标识。
这个键的值可以是任意类型的,默认是个ObjectId对象。对象id设计成轻量型的,不同的机器都能用全局唯一的同种方法方便的生成它。这对于在分片环境中生成唯一的标示符非常重要。
ObjectId的前4个字节是从标准纪元开始的时间戳,单位为秒。这会带来一些有用的属性。
- 时间戳,与随后的5字节组合起来,提供了秒级别的唯一性。
- 由于时间戳在前,这意味着objectid大致会按插入的顺序排列。
- 这4字节也隐含了创建文档的时间。绝大多数驱动程序都会提供一个方法,用于从objectId获取这些信息。
接下来的3字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以确保不同主机生成不同的objectId,不产生冲突。
为了确保在同一机器上并发的多个进程产生的ObjectId是唯一的,接下来的两个字节来自产生objectId的进程的进程标识符PID。
前9字节保证了同一秒钟不同机器不同进程产生的ObjectId是唯一的。最后3字节是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId也是不一样的。一秒钟最多允许每个进程拥有2563个不同的ObjectId。
如果插入文档时没有“_id”键,系统会自动帮你创建一个。可以由MongoDB服务完成,但通常会在客户端由驱动程序完成。
二进制数据
二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要将非utf-8字符保存在数据库中,二进制数据是唯一的方式。
代码
查询和文档中可以包含任意js代码 {“x”:function(){/*...*/}}
另外,有几种大多数情况仅在内部使用(或被其他类型取代)的类型。
使用MongoDB shell
将shell连接到任何MongoDB实例:mongo 机器名:端口/数据库名
下面使用我的Linux连接我的Windows
[root@yang mongodb]# ./bin/mongo 192.168.1.111:27017/test MongoDB shell version: 3.2.10 connecting to: 192.168.1.111:27017/test Server has startup warnings: 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] > show dbs admin 0.000GB local 0.000GB test 0.000GB > db.test.find() > db.test.insert({"x":100}) WriteResult({ "nInserted" : 1 }) > > db.test.find() { "_id" : ObjectId("584fe47a36b03fda10897c99"), "x" : 100 }
在我的windows中查看效果
启动时不连接任何数据库,使用 --nodb 参数启动shell,启动之后,在需要时运行new Mongo(hostname)命令就可以连接到想要的mongod了。任何时候都可以使用这些命令来连接到不同的数据库或者服务器。
[root@yang mongodb]# ./bin/mongo --nodb MongoDB shell version: 3.2.10 > conn=new Mongo("192.168.1.111:27017") connection to 192.168.1.111:27017 > db=conn.getDB("test") test > db.test.find() { "_id" : ObjectId("584fe47a36b03fda10897c99"), "x" : 100 }
Shell内置了帮助文档,可以使用 help 命令查看,可以通过db.help()查看数据库级别的帮助,使用db.foo.help()查看集合级别的帮助,使用db.foo.update方式查看函数的js实现代码。
> 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执行脚本
mongo shell会依次执行传入的脚本,然后退出。
E:\\Program Files\\MongoDB\\Server\\3.4\\bin>mongo js1.js MongoDB shell version v3.4.0-rc3-7-ge24e12c connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.0-rc3-7-ge24e12c I am yyb in the script1.js
首先:脚本的位置须放在mongo.exe 所在的目录,也就是bin目录下。其次如果配置了环境变量,直接mongo js1.js是不行的。比如:
C:\\Users\\yang>mongo js1.js 2016-12-13T21:25:36.265+0800 E - [main] file [js1.js] doesn\'t exist failed to load: js1.js
使用指定的主机/端口上的mongod运行脚本,需要先指定地址,然后再跟上脚本的文件的名称。
在脚本中使用print()函数将内容输出到标准输出,这样就可以在shell中使用管道命令。如果将shell脚本的输出管道给另一个使用--quiet选项的命令,就可以让shell不打印“MongoDB shell version...”提示。
[root@yang bin]# ./mongo --quiet 192.168.1.111:27017/test js1.js
I like to read and study
可以使用load()函数,从交互式shell中运行脚本:
> load("js1.js") I like to read and study true
在脚本中可以访问db变量,以及其他全局变量。然而,shell辅助函数(比如:“use db”和“show collections”)不可以在文件中使用。不过,这些辅助函数都有对应的js函数。
可以使用脚本将变量注入到shell
/** *连接到指定的数据库,并且将db指向这个连接 */ var connectTo=function(port,dbname){ if(!port){ port=27017; } if (!dbname) { dbname="test"; } db=connect("localhost:"+port+"/"+dbname); return db; }
如果在shell中加载这个脚本,connectTo函数就可以使用了。
> typeof connectTo undefined > load("defineConnectTo.js") true > typeof connectTo function
除了添加辅助函数,还可以使用脚本将通用的任务和管理活动自动化。默认情况,shell会在运行shell时所处的目录中查找脚本(可以使用run(“pwd”)命令查看)。可以为shell指定一个相对路径或者绝对路径。
> load("/usr/local/mongodb/js1.js") i am studing mongodb 2016-12-14T19:36:01.744+0800 I - [thread1] shell: started program (sh6054): pwd sh6054| /usr/local/mongodb true
也可以在shell中使用run()函数来执行命令行程序。可以在函数参数列表中指定程序所需的参数。通常来说,这种使用方式的局限性非常大,因为输出格式很奇怪,而且不支持管道。
> run("ls","-l","/usr/local/mongodb/") 2016-12-14T19:40:23.878+0800 I - [thread1] shell: started program (sh6098): ls -l /usr/local/mongodb/ sh6098| 总用量 104 sh6098| drwxrwxr-x. 2 yang yang 4096 12月 13 23:31 bin sh6098| -rw-r--r--. 1 yang yang 34520 9月 30 18:46 GNU-AGPL-3.0 sh6098| -rw-r--r--. 1 root root 43 12月 14 19:34 js1.js sh6098| -rw-r--r--. 1 yang yang 16726 9月 30 18:46 MPL-2 sh6098| -rw-r--r--. 1 yang yang 1359 9月 30 18:46 README sh6098| -rw-r--r--. 1 yang yang 35910 9月 30 18:46 THIRD-PARTY-NOTICES 0
创建.mongorc.js文件
如果某些脚本会被频繁加载,可以将它们添加到mongorc.js文件中。这个文件会在启动shell时自动运行。
Win10中,这个文件所在位置: C:\\Users\\yang ,Linux中,不知道哪个是用户主目录,对linux不熟悉。在home目录中创建了这个文件没什么效果。
C:\\Windows\\system32>mongo MongoDB shell version v3.4.0-rc3-7-ge24e12c connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.0-rc3-7-ge24e12c Hello,i am studing mongodb// 在文件中写了print这句话 Server has startup warnings: 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] >
可以使用这个脚本创建一些自己需要的全局变量,或者是为太长的名字创建一个简短的别名,也可以重写内置的函数。最常见的用途之一是移除那些比较“危险”的shell辅助函数。
改变数据库函数时,要确保同时对db变量和DB原型进行改变。如果只改变了其中一个,那么db变量可能没有改变,或者这些改变在新使用的所有数据库中都不会生效。比如:
var no=function(){ print("Not on my watch."); } //禁止删除数据库 db.dropDatebase=DB.prototype.dropDatabase=no; //禁止删除集合 DBCollection.prototype.drop=no; //禁止删除索引 DBCollection.prototype.dropIndex=no;
如果在启动shell时指定 --norc 参数,就可以禁止加载.mongorc.js。
可以在.mongorc.js中定制自己想要的提示。将prompt变量设为一个字符串或者返回字符串的函数。就可以重写默认的shell提示。也可以定制多个提示,在shell中可以自由切换。
C:\\Windows\\system32>mongo MongoDB shell version v3.4.0-rc3-7-ge24e12c connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.0-rc3-7-ge24e12c Server has startup warnings: 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2016-12-12T14:14:40.558+0800 I CONTROL [initandlisten] test>
在shell中设置EDITOR变量调用编辑器,在windows中貌似不认。
> EDITOR="/usr/bin/emacs" > var wap=db.books.findOne({title:"war and peace"}) > edit wap
在.mongorc.js文件中添加一行EDITOR="编辑器路径";,以后就不必单独设了。
集合命名注意事项
可以使用db.collectionName获取一个集合的内容,但是,如果集合名称重包含保留字或者无效的js属性名称,就不行了。
> db.test test.test > db.version function () { return this.serverBuildInfo().version; }
如果集合中包含无效的js属性名称,可以使用getCollection函数:
> db.getCollection("version")
test.version
也可以使用数组访问语法,访问以无效属性命名的集合。
> collections=["po-sts","123comments","authors"];
[ "po-sts", "123comments", "authors" ]
> for(var i in collections){ print(db.blog[collections[i]]); }
blog.blog.po-sts
blog.blog.123comments
blog.blog.authors
以上是关于MongoDB权威指南第二版学习笔记二的主要内容,如果未能解决你的问题,请参考以下文章
《Ansible权威指南》笔记——安装,ssh密钥登陆,命令