數據類型
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