首页 > 代码库 > MongoDB权威指南第二版学习笔记二

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.10connecting to: 192.168.1.111:27017/testServer 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 dbsadmin  0.000GBlocal  0.000GBtest   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 --nodbMongoDB 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.jsMongoDB shell version v3.4.0-rc3-7-ge24e12cconnecting to: mongodb://127.0.0.1:27017MongoDB server version: 3.4.0-rc3-7-ge24e12cI am yyb in the script1.js

首先:脚本的位置须放在mongo.exe 所在的目录,也就是bin目录下。其次如果配置了环境变量,直接mongo js1.js是不行的。比如:

C:\Users\yang>mongo js1.js2016-12-13T21:25:36.265+0800 E - [main] file [js1.js] doesn‘t existfailed 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.jsI like to read and study

可以使用load()函数,从交互式shell中运行脚本:

> load("js1.js")I like to read and studytrue

在脚本中可以访问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;}
> typeof connectToundefined> load("defineConnectTo.js")true> typeof connectTofunction

如果在shell中加载这个脚本,connectTo函数就可以使用了。

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