MongoDB权威指南第二版学习笔记二

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB权威指南第二版学习笔记二相关的知识,希望对你有一定的参考价值。

数据类型

MongoDB在保留JSON基本键/值对特性的基础上,添加了其他一些数据类型。

null

null用于表示空值或者不存在的字段:{“x”:null} 

布尔型

布尔类型有两个值truefalse {“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权威指南第二版学习笔记二的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB权威指南第二版学习笔记—增删改文档下

《Ansible权威指南》笔记——安装,ssh密钥登陆,命令

读《Android开发权威指南》

js-权威指南学习笔记14

《Android权威编程指南(The Big Nerd Ranch Guide)(第二版)》12.4挑战练习

[权威指南]学习笔记——第5章 索引