MongoDB學習筆記二—Shell操作


數據類型

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM