您好,登錄后才能下訂單哦!
本篇文章為大家展示了Mongodb體系結構與客戶端基本操作及注意細節有哪些,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
說到Mongodb的體系結構,免不了與關系型數據庫做個對比。這里以MySQL為例,我們進行一些比較:
從邏輯結構上對比:
MySQL層次概念 MongoDB層次概念
數據庫(database) 數據庫(database)
表(table) 集合(collection)
記錄(row) 文檔(document)
在MongoDB中沒有行、列、關系的概念,集合中的文檔相當于一條記錄,這體現了模式自由的特點。
從數據存儲結構上對比:
MySQL的每個數據庫存放在一個與數據庫同名的文件夾中,MySQL如果使用MyISAM存儲引擎,數據庫文件類型就包括.frm、.MYD(存放數據,D為Data)、.MYI(存放索引,I為Index)。
MongoDB的默認數據目錄時/data/db,它負責存儲所有MongoDB的數據文件。在MongoDB內部,每個數據庫都包含一個.ns文件和一些數據文件,而且這些數據文件會隨著數據量的增加而變得越來越多,例如系統中有一個叫mydb的數據庫,那么構成mydb這個數據庫的文件就會有mydb.ns,mydb.0,mydb.1等等組成。
mydb.ns記錄了數據庫Json對象的命名空間(ns時namespace的縮寫),也就是數據庫集合里面的命名空間。mydb.0和mydb.1是存放數據庫mydb的對象的空間,且大小按照2的n次方大小遞增。如mydb.`0的大小是16M,當數據庫mydb存滿16M之后,就會形成生成mydb.1繼續存儲,mydb.1的大小為32M,以此類推,隨著數據的增加,還會有mydb.2、mydb.3等文件出現,大小64M、128M。默認情況下,現在版本的Mongodb在數據庫剛剛建立時就會預先分配好XXX.0和XXX.1共48M空間,之后再隨著插入對象的增多而生成后續xxx.2等。
MongoDB客戶段基本操作:
首先當然是要確認MongoDB的mongod服務是打開的。詳細見我之前的博客。
打開MongoDB客戶端的方法時運行MongoDB的bin目錄下的mongo。
[neil@neilhost Downloads]$ pstree -p | grep mongod |-mongod(3556)-+-{mongod}(3557) | |-{mongod}(3558) | |-{mongod}(3559) | |-{mongod}(3563) | |-{mongod}(3564) | |-{mongod}(3565) | |-{mongod}(3566) | |-{mongod}(3567) | `-{mongod}(3568) [neil@neilhost Downloads]$ cd /usr/local/mongodb/bin/mongo bash: cd: /usr/local/mongodb/bin/mongo: 不是目錄 [neil@neilhost Downloads]$ sudo /usr/local/mongodb/bin/mongo MongoDB shell version: 2.6.8 connecting to: test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user
接下來介紹幾個基本操作,以及一個細節。
show dbs的意思是顯示mongodb中所有的數據庫。剛安裝好mongodb時,默認有兩個數據庫admin和local,不去管他們。
db指的是當前工作環境所在的數據庫。當你每次進入mongo時。默認進入的數據庫時test,它是一個隱式存儲的數據庫,如果需要進入特定的數據庫,或是想建立一個新的數據庫,只需要“use 數據庫名稱”就可以了。在mongodb中不需要create database這種操作,想用就用,mongodb會自動幫我們建立了數據庫,就像一個服務周到的“黑執事”。這里,我use dt2建立了一個新的數據庫dt2,客戶端立即現實工作環境轉入到dt2。但是,如果你show dbs,發現數據庫并沒有真正建立。是需要新建表并且插入一些數據才可以嗎?不是,只需要你在當前數據庫dt2輸入任何一個細小的操作命令,如顯示當前數據庫的集合有哪些,這時候dt2就會被真正建立了。
connecting to: test > show dbs admin (empty) dt1 0.078GB local 0.078GB > db test > use dt2 switched to db dt2 > show dbs admin (empty) dt1 0.078GB local 0.078GB > show collections > show dbs admin (empty) dt1 0.078GB dt2 (empty) local 0.078GB
在上面的命令中,show collections是顯示當前數據庫下的集合有哪些。因為現在還沒有集合,所以什么都不顯示。
接下來我們嘗試建立集合和插入數據。
> db.student.find() > show collections >
mongodb建立集合(表),依然是一個不需要聲明著建立表的過程。即不需要create collection或create table之類操作。
直接用即可。
這里我們依舊首先驗證一個小細節。什么樣子的表操作才會導致表的生成。通過上面的命令。我們在還沒有student集合的時候對其進行查詢(find()),但是,之后顯示集合的命令可以看到并沒有為dt2建立student集合。
于是我直接在student表中插入一個Json對象(存儲在Mongodb的單元是Bson對象,在邏輯概念上是一個文檔)
> db.student.insert({name:"Viper",age:20}) WriteResult({ "nInserted" : 1 }) > show collections student system.indexes >
這時候,當show collections的時候可以看見,student集合已經有了。這說明在建立集合時,必須想新的集合中插入有效數據,才能真正建立集合。
總結上面的兩個細節就是,在MongoDB中建立數據庫時,只要use數據庫,并且在數據庫下執行任何看似不會有任何影響的命令,如查詢集合,都會使得數據庫建立起來;但是,如果在數據庫下,對于新建集合的文檔查詢是不會導致集合建立的,必須有文檔數據插入集合,才能使得集合真正建立起來。這樣一對細節很多人未必知道!
另外當空數據庫建立集合時,會生成一個索引表,system.indexes。該數據庫下的所有集合的ObjectId的索引值全都存放在這里面。
那么下面我們來分別說說增刪改查。
增
前面的例子中其實已經加入了一條文檔,這里我們在增加一個文檔到student集合。
> db.student.insert({name:"TA",age:18,phone:["1311234567","021-87658765"],GPA:{Math:88,English:99}}) WriteResult({ "nInserted" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } >
這里可以看到,我向mongodb的student集合中插入的兩個文檔,它們的“表結構”是不一樣的。這就是NoSQL數據庫與關系型數據庫的最重要區別之一(其他區別之前也提過,ACID特性(事務的支持),并發)。
其中第二條文檔中我們看到key-value的value可以是一些數、字符串等基本類型外,還可以是數組(其實可以理解為棧,后面的博客文章會介紹value是數組情況下的push和pop,所以理解為一種類似于棧的列表更妥貼),如上面的phone鍵。更強大的地方是,文檔,即插入的Json對象的keybalue的value可以是另一個Json對象,如上面的GPA鍵。
其實,這些數組、json對象更像是python語法中的列表和字典,哈哈哈哈。。。
這里,我將key-value的value數據類型做個整理:
null: 表示空值或者不存在的值
布爾類型: true和false,如{male:true}
32位整數: Mongodb的控制臺使用JS引擎進行輸入,而JS僅僅支持64位浮點數,所以32位整數會被自動轉義
64位整數: 同上,會被自動轉義成64位浮點數
64位浮點數: Mongodb的控制臺數字的默認類型。如{salary:23871.12}
字符串 :UTF-8字符串都可以表示為字符串類型的數據
符號: 在MongoDB中不支持這種類型,將自動轉義成字符串
ObjectId: MongoDB獨有,對象id時文檔中***的12位16進制的id。(時間戳 | 機器 | PID | 計數器)
日期: 注意:使用的時候要加上new。如{birthday:new Date()}
正則表達式: 文檔鍵值可以包含正則表達式,其正則表達式采用JS語法來表示。如:{key:/ho/i}
代碼: 文檔中可以包含JS文檔。如{key:function(){/*........*/}}(可以是沒有函數名的匿名函數)
數組:文檔中的key的value可以表示為數組,數組內還可以嵌套數組。
內嵌文檔: 文檔可以包含別的文檔,也可以作為value嵌入到父文檔中。如{x:{name:"happyBKs",age:2}}
插入之后的Json對象我們可以看到,新插入的每個文檔都被賦予了一個_id,這是可以理解為記錄的主,是mongodb自動生存成的key,它的value是一個特定的ObjectId對象,是一個96位二進制數,由機器碼、機器進程號、時間、當前命名空間的編號四個部分自動生成,***。當然,如果你愿意,也可以在插入Json對象時自己指定_id的value,只要未發生主鍵沖突,都可以正常插入。
增加一個記錄除了用insert方法之外還有一種方法,那就是save。它的功能是當你指定Json的_id,并且_id在集合中已經存在,那么它會更新相應的文檔;否則,則插入一個新的文檔。請看下面這個例子,_id的為1的Json對象,***次save是被添加,而第二次則是被更改。
> db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } > db.student.save({_id:1,name:"happyBKs",age:0}) WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "name" : "happyBKs", "age" : 0 } > db.student.save({_id:1,name:"hahaBKs",age:2}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "name" : "hahaBKs", "age" : 2 } >
改
更改的操作用的是update方法。
用法為: db.collection.update({...},{...})
參數有兩個,***個指定要改誰,第二個指定改成什么。
但是事情沒有這么簡單,請看下面的例子。原本的打算是將名字為hahaBKs的記錄增加一個性別字段,但是發現除了_id的所有字段都被覆蓋掉了,只剩下了gender。這顯然不是我們的預想的結果。
> db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "name" : "hahaBKs", "age" : 2 } > > db.student.update({name:"hahaBKs"},{gender:"male"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "gender" : "male" } >
那么問題出在哪里呢?這里我們需要用到的一個操作符$set,具體的用法以后的文章李會詳細來說。
下面我直接給出一個解決辦法的示例,如下:
> db.student.insert({name:"TB",age:11,gender:"male",room:"301"}) WriteResult({ "nInserted" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "gender" : "male" } { "_id" : ObjectId("54fc521d3fc8173ba3302e6e"), "name" : "TB", "age" : 11, "gender" : "male", "room" : "301" } > db.student.update({name:"TB"},{$set:{age:22,classid:"1515"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.student.find() { "_id" : ObjectId("54fb0d853fc8173ba3302e6c"), "name" : "Viper", "age" : 20 } { "_id" : ObjectId("54fb10493fc8173ba3302e6d"), "name" : "TA", "age" : 18, "phone" : [ "1311234567", "021-87658765" ], "GPA" : { "Math" : 88, "English" : 99 } } { "_id" : 1, "gender" : "male" } { "_id" : ObjectId("54fc521d3fc8173ba3302e6e"), "name" : "TB", "age" : 22, "gender" : "male", "room" : "301", "classid" : "1515" } >
上面的例子是,增加了一個name叫TB的對象,然后對其進行更改,更改的內容包括,將原有age鍵的值11改成22,并增加一個新的鍵classid賦值“1515”。這里需要用到的操作符就是$set,用于設置鍵的值。
刪
刪除的方法是remove。
用法是 db.collection.remove({...})
參數里寫明想需要刪除的對象的條件。
注意,當參數空著,或者空的Json對象。即db.collection.remove()和db.collection.remove({}),將把該集合中的所有文檔全部刪除!!!
> db.class.insert({classname:"English",teacher:"Mr A"}) WriteResult({ "nInserted" : 1 }) > db.class.insert({classname:"Math",teacher:"Mr B"}) WriteResult({ "nInserted" : 1 }) > db.class.find() { "_id" : ObjectId("54fc54773fc8173ba3302e6f"), "classname" : "English", "teacher" : "Mr A" } { "_id" : ObjectId("54fc54833fc8173ba3302e70"), "classname" : "Math", "teacher" : "Mr B" } > db.class.remove({classname:"English"}) WriteResult({ "nRemoved" : 1 }) > db.class.find() { "_id" : ObjectId("54fc54833fc8173ba3302e70"), "classname" : "Math", "teacher" : "Mr B" } > > db.class.remove({}) WriteResult({ "nRemoved" : 1 }) > db.class.find() >
上面的例子中新建了一個class集合,并插入兩個文檔。其中種種,自己看吧。
查
用法兩種
db.collection.find({....}),其中參數是查詢對象的條件。如果find()或find({})就是全查,這和remove很類似。
db.collection.findOne({...})和find相似,但是它只會返回***個查詢到的符合條件的對象。
> db.class.insert({classname:"English",teacher:"Mr AAA"})
WriteResult({ "nInserted" : 1 })
> db.class.insert({classname:"English",teacher:"Mr ZZZ"})
WriteResult({ "nInserted" : 1 })
> db.class.insert({classname:"English",teacher:"Mr WWW"})
WriteResult({ "nInserted" : 1 })
> db.class.insert({classname:"English",teacher:"Mr SSS"})
WriteResult({ "nInserted" : 1 })
> db.class.insert({classname:"French",teacher:"Mr SSS"})
WriteResult({ "nInserted" : 1 })
> db.class.find({})
{ "_id" : ObjectId("54fc562e3fc8173ba3302e71"), "classname" : "English", "teacher" : "Mr AAA" }
{ "_id" : ObjectId("54fc56373fc8173ba3302e72"), "classname" : "English", "teacher" : "Mr ZZZ" }
{ "_id" : ObjectId("54fc56413fc8173ba3302e73"), "classname" : "English", "teacher" : "Mr WWW" }
{ "_id" : ObjectId("54fc564e3fc8173ba3302e74"), "classname" : "English", "teacher" : "Mr SSS" }
{ "_id" : ObjectId("54fc56603fc8173ba3302e75"), "classname" : "French", "teacher" : "Mr SSS" }
> db.class.findOne({classname:"English"})
{
"_id" : ObjectId("54fc562e3fc8173ba3302e71"),
"classname" : "English",
"teacher" : "Mr AAA"
}
> db.class.find({classname:"English"})
{ "_id" : ObjectId("54fc562e3fc8173ba3302e71"), "classname" : "English", "teacher" : "Mr AAA" }
{ "_id" : ObjectId("54fc56373fc8173ba3302e72"), "classname" : "English", "teacher" : "Mr ZZZ" }
{ "_id" : ObjectId("54fc56413fc8173ba3302e73"), "classname" : "English", "teacher" : "Mr WWW" }
{ "_id" : ObjectId("54fc564e3fc8173ba3302e74"), "classname" : "English", "teacher" : "Mr SSS" }
>
上述內容就是Mongodb體系結構與客戶端基本操作及注意細節有哪些,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。