溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Mongodb體系結(jié)構(gòu)與客戶端基本操作及注意細(xì)節(jié)有哪些

發(fā)布時(shí)間:2021-11-03 10:33:36 來(lái)源:億速云 閱讀:143 作者:柒染 欄目:數(shù)據(jù)庫(kù)

本篇文章為大家展示了Mongodb體系結(jié)構(gòu)與客戶端基本操作及注意細(xì)節(jié)有哪些,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

說(shuō)到Mongodb的體系結(jié)構(gòu),免不了與關(guān)系型數(shù)據(jù)庫(kù)做個(gè)對(duì)比。這里以MySQL為例,我們進(jìn)行一些比較:

從邏輯結(jié)構(gòu)上對(duì)比:

MySQL層次概念             MongoDB層次概念

數(shù)據(jù)庫(kù)(database)     數(shù)據(jù)庫(kù)(database)

表(table)                     集合(collection)

記錄(row)                   文檔(document)

在MongoDB中沒(méi)有行、列、關(guān)系的概念,集合中的文檔相當(dāng)于一條記錄,這體現(xiàn)了模式自由的特點(diǎn)。

從數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)上對(duì)比:

MySQL的每個(gè)數(shù)據(jù)庫(kù)存放在一個(gè)與數(shù)據(jù)庫(kù)同名的文件夾中,MySQL如果使用MyISAM存儲(chǔ)引擎,數(shù)據(jù)庫(kù)文件類(lèi)型就包括.frm、.MYD(存放數(shù)據(jù),D為Data)、.MYI(存放索引,I為Index)。

MongoDB的默認(rèn)數(shù)據(jù)目錄時(shí)/data/db,它負(fù)責(zé)存儲(chǔ)所有MongoDB的數(shù)據(jù)文件。在MongoDB內(nèi)部,每個(gè)數(shù)據(jù)庫(kù)都包含一個(gè).ns文件和一些數(shù)據(jù)文件,而且這些數(shù)據(jù)文件會(huì)隨著數(shù)據(jù)量的增加而變得越來(lái)越多,例如系統(tǒng)中有一個(gè)叫mydb的數(shù)據(jù)庫(kù),那么構(gòu)成mydb這個(gè)數(shù)據(jù)庫(kù)的文件就會(huì)有mydb.ns,mydb.0,mydb.1等等組成。

mydb.ns記錄了數(shù)據(jù)庫(kù)Json對(duì)象的命名空間(ns時(shí)namespace的縮寫(xiě)),也就是數(shù)據(jù)庫(kù)集合里面的命名空間。mydb.0和mydb.1是存放數(shù)據(jù)庫(kù)mydb的對(duì)象的空間,且大小按照2的n次方大小遞增。如mydb.`0的大小是16M,當(dāng)數(shù)據(jù)庫(kù)mydb存滿16M之后,就會(huì)形成生成mydb.1繼續(xù)存儲(chǔ),mydb.1的大小為32M,以此類(lèi)推,隨著數(shù)據(jù)的增加,還會(huì)有mydb.2、mydb.3等文件出現(xiàn),大小64M、128M。默認(rèn)情況下,現(xiàn)在版本的Mongodb在數(shù)據(jù)庫(kù)剛剛建立時(shí)就會(huì)預(yù)先分配好XXX.0和XXX.1共48M空間,之后再隨著插入對(duì)象的增多而生成后續(xù)xxx.2等。

MongoDB客戶段基本操作:

首先當(dāng)然是要確認(rèn)MongoDB的mongod服務(wù)是打開(kāi)的。詳細(xì)見(jiàn)我之前的博客。

打開(kāi)MongoDB客戶端的方法時(shí)運(yùn)行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

接下來(lái)介紹幾個(gè)基本操作,以及一個(gè)細(xì)節(jié)。

show dbs的意思是顯示mongodb中所有的數(shù)據(jù)庫(kù)。剛安裝好mongodb時(shí),默認(rèn)有兩個(gè)數(shù)據(jù)庫(kù)admin和local,不去管他們。

db指的是當(dāng)前工作環(huán)境所在的數(shù)據(jù)庫(kù)。當(dāng)你每次進(jìn)入mongo時(shí)。默認(rèn)進(jìn)入的數(shù)據(jù)庫(kù)時(shí)test,它是一個(gè)隱式存儲(chǔ)的數(shù)據(jù)庫(kù),如果需要進(jìn)入特定的數(shù)據(jù)庫(kù),或是想建立一個(gè)新的數(shù)據(jù)庫(kù),只需要“use 數(shù)據(jù)庫(kù)名稱(chēng)”就可以了。在mongodb中不需要create database這種操作,想用就用,mongodb會(huì)自動(dòng)幫我們建立了數(shù)據(jù)庫(kù),就像一個(gè)服務(wù)周到的“黑執(zhí)事”。這里,我use dt2建立了一個(gè)新的數(shù)據(jù)庫(kù)dt2,客戶端立即現(xiàn)實(shí)工作環(huán)境轉(zhuǎn)入到dt2。但是,如果你show dbs,發(fā)現(xiàn)數(shù)據(jù)庫(kù)并沒(méi)有真正建立。是需要新建表并且插入一些數(shù)據(jù)才可以嗎?不是,只需要你在當(dāng)前數(shù)據(jù)庫(kù)dt2輸入任何一個(gè)細(xì)小的操作命令,如顯示當(dāng)前數(shù)據(jù)庫(kù)的集合有哪些,這時(shí)候dt2就會(huì)被真正建立了。

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是顯示當(dāng)前數(shù)據(jù)庫(kù)下的集合有哪些。因?yàn)楝F(xiàn)在還沒(méi)有集合,所以什么都不顯示。

接下來(lái)我們嘗試建立集合和插入數(shù)據(jù)。

> db.student.find() > show collections >

mongodb建立集合(表),依然是一個(gè)不需要聲明著建立表的過(guò)程。即不需要create collection或create table之類(lèi)操作。

直接用即可。

這里我們依舊首先驗(yàn)證一個(gè)小細(xì)節(jié)。什么樣子的表操作才會(huì)導(dǎo)致表的生成。通過(guò)上面的命令。我們?cè)谶€沒(méi)有student集合的時(shí)候?qū)ζ溥M(jìn)行查詢(xún)(find()),但是,之后顯示集合的命令可以看到并沒(méi)有為dt2建立student集合。

于是我直接在student表中插入一個(gè)Json對(duì)象(存儲(chǔ)在Mongodb的單元是Bson對(duì)象,在邏輯概念上是一個(gè)文檔)

> db.student.insert({name:"Viper",age:20}) WriteResult({ "nInserted" : 1 }) > show collections student system.indexes >

這時(shí)候,當(dāng)show collections的時(shí)候可以看見(jiàn),student集合已經(jīng)有了。這說(shuō)明在建立集合時(shí),必須想新的集合中插入有效數(shù)據(jù),才能真正建立集合。

總結(jié)上面的兩個(gè)細(xì)節(jié)就是,在MongoDB中建立數(shù)據(jù)庫(kù)時(shí),只要use數(shù)據(jù)庫(kù),并且在數(shù)據(jù)庫(kù)下執(zhí)行任何看似不會(huì)有任何影響的命令,如查詢(xún)集合,都會(huì)使得數(shù)據(jù)庫(kù)建立起來(lái);但是,如果在數(shù)據(jù)庫(kù)下,對(duì)于新建集合的文檔查詢(xún)是不會(huì)導(dǎo)致集合建立的,必須有文檔數(shù)據(jù)插入集合,才能使得集合真正建立起來(lái)。這樣一對(duì)細(xì)節(jié)很多人未必知道!

另外當(dāng)空數(shù)據(jù)庫(kù)建立集合時(shí),會(huì)生成一個(gè)索引表,system.indexes。該數(shù)據(jù)庫(kù)下的所有集合的ObjectId的索引值全都存放在這里面。

那么下面我們來(lái)分別說(shuō)說(shuō)增刪改查。

前面的例子中其實(shí)已經(jīng)加入了一條文檔,這里我們?cè)谠黾右粋€(gè)文檔到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集合中插入的兩個(gè)文檔,它們的“表結(jié)構(gòu)”是不一樣的。這就是NoSQL數(shù)據(jù)庫(kù)與關(guān)系型數(shù)據(jù)庫(kù)的最重要區(qū)別之一(其他區(qū)別之前也提過(guò),ACID特性(事務(wù)的支持),并發(fā))。

其中第二條文檔中我們看到key-value的value可以是一些數(shù)、字符串等基本類(lèi)型外,還可以是數(shù)組(其實(shí)可以理解為棧,后面的博客文章會(huì)介紹value是數(shù)組情況下的push和pop,所以理解為一種類(lèi)似于棧的列表更妥貼),如上面的phone鍵。更強(qiáng)大的地方是,文檔,即插入的Json對(duì)象的keybalue的value可以是另一個(gè)Json對(duì)象,如上面的GPA鍵。

其實(shí),這些數(shù)組、json對(duì)象更像是python語(yǔ)法中的列表和字典,哈哈哈哈。。。

這里,我將key-value的value數(shù)據(jù)類(lèi)型做個(gè)整理:

  • null: 表示空值或者不存在的值

  • 布爾類(lèi)型: true和false,如{male:true}

  • 32位整數(shù): Mongodb的控制臺(tái)使用JS引擎進(jìn)行輸入,而JS僅僅支持64位浮點(diǎn)數(shù),所以32位整數(shù)會(huì)被自動(dòng)轉(zhuǎn)義

  • 64位整數(shù): 同上,會(huì)被自動(dòng)轉(zhuǎn)義成64位浮點(diǎn)數(shù)

  • 64位浮點(diǎn)數(shù): Mongodb的控制臺(tái)數(shù)字的默認(rèn)類(lèi)型。如{salary:23871.12}

  • 字符串 :UTF-8字符串都可以表示為字符串類(lèi)型的數(shù)據(jù)

  • 符號(hào): 在MongoDB中不支持這種類(lèi)型,將自動(dòng)轉(zhuǎn)義成字符串

  • ObjectId: MongoDB獨(dú)有,對(duì)象id時(shí)文檔中***的12位16進(jìn)制的id。(時(shí)間戳 | 機(jī)器 | PID | 計(jì)數(shù)器)

  • 日期: 注意:使用的時(shí)候要加上new。如{birthday:new Date()}

  • 正則表達(dá)式: 文檔鍵值可以包含正則表達(dá)式,其正則表達(dá)式采用JS語(yǔ)法來(lái)表示。如:{key:/ho/i}

  • 代碼: 文檔中可以包含JS文檔。如{key:function(){/*........*/}}(可以是沒(méi)有函數(shù)名的匿名函數(shù))

  • 數(shù)組:文檔中的key的value可以表示為數(shù)組,數(shù)組內(nèi)還可以嵌套數(shù)組。

  • 內(nèi)嵌文檔: 文檔可以包含別的文檔,也可以作為value嵌入到父文檔中。如{x:{name:"happyBKs",age:2}}

插入之后的Json對(duì)象我們可以看到,新插入的每個(gè)文檔都被賦予了一個(gè)_id,這是可以理解為記錄的主,是mongodb自動(dòng)生存成的key,它的value是一個(gè)特定的ObjectId對(duì)象,是一個(gè)96位二進(jìn)制數(shù),由機(jī)器碼、機(jī)器進(jìn)程號(hào)、時(shí)間、當(dāng)前命名空間的編號(hào)四個(gè)部分自動(dòng)生成,***。當(dāng)然,如果你愿意,也可以在插入Json對(duì)象時(shí)自己指定_id的value,只要未發(fā)生主鍵沖突,都可以正常插入。

增加一個(gè)記錄除了用insert方法之外還有一種方法,那就是save。它的功能是當(dāng)你指定Json的_id,并且_id在集合中已經(jīng)存在,那么它會(huì)更新相應(yīng)的文檔;否則,則插入一個(gè)新的文檔。請(qǐng)看下面這個(gè)例子,_id的為1的Json對(duì)象,***次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({...},{...})

參數(shù)有兩個(gè),***個(gè)指定要改誰(shuí),第二個(gè)指定改成什么。

但是事情沒(méi)有這么簡(jiǎn)單,請(qǐng)看下面的例子。原本的打算是將名字為hahaBKs的記錄增加一個(gè)性別字段,但是發(fā)現(xiàn)除了_id的所有字段都被覆蓋掉了,只剩下了gender。這顯然不是我們的預(yù)想的結(jié)果。

> 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" } >

那么問(wèn)題出在哪里呢?這里我們需要用到的一個(gè)操作符$set,具體的用法以后的文章李會(huì)詳細(xì)來(lái)說(shuō)。

下面我直接給出一個(gè)解決辦法的示例,如下:

> 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" } >

上面的例子是,增加了一個(gè)name叫TB的對(duì)象,然后對(duì)其進(jìn)行更改,更改的內(nèi)容包括,將原有age鍵的值11改成22,并增加一個(gè)新的鍵classid賦值“1515”。這里需要用到的操作符就是$set,用于設(shè)置鍵的值。

刪除的方法是remove。

用法是 db.collection.remove({...})

參數(shù)里寫(xiě)明想需要?jiǎng)h除的對(duì)象的條件。

注意,當(dāng)參數(shù)空著,或者空的Json對(duì)象。即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() >

上面的例子中新建了一個(gè)class集合,并插入兩個(gè)文檔。其中種種,自己看吧。

用法兩種

db.collection.find({....}),其中參數(shù)是查詢(xún)對(duì)象的條件。如果find()或find({})就是全查,這和remove很類(lèi)似。

db.collection.findOne({...})和find相似,但是它只會(huì)返回***個(gè)查詢(xún)到的符合條件的對(duì)象。

  1. > db.class.insert({classname:"English",teacher:"Mr AAA"}) 

  2. WriteResult({ "nInserted" : 1 }) 

  3. > db.class.insert({classname:"English",teacher:"Mr ZZZ"}) 

  4. WriteResult({ "nInserted" : 1 }) 

  5. > db.class.insert({classname:"English",teacher:"Mr WWW"}) 

  6. WriteResult({ "nInserted" : 1 }) 

  7. > db.class.insert({classname:"English",teacher:"Mr SSS"}) 

  8. WriteResult({ "nInserted" : 1 }) 

  9. > db.class.insert({classname:"French",teacher:"Mr SSS"}) 

  10. WriteResult({ "nInserted" : 1 }) 

  11. > db.class.find({}) 

  12. { "_id" : ObjectId("54fc562e3fc8173ba3302e71"), "classname" : "English", "teacher" : "Mr AAA" } 

  13. { "_id" : ObjectId("54fc56373fc8173ba3302e72"), "classname" : "English", "teacher" : "Mr ZZZ" } 

  14. { "_id" : ObjectId("54fc56413fc8173ba3302e73"), "classname" : "English", "teacher" : "Mr WWW" } 

  15. { "_id" : ObjectId("54fc564e3fc8173ba3302e74"), "classname" : "English", "teacher" : "Mr SSS" } 

  16. { "_id" : ObjectId("54fc56603fc8173ba3302e75"), "classname" : "French", "teacher" : "Mr SSS" } 

  17. > db.class.findOne({classname:"English"}) 

  18. "_id" : ObjectId("54fc562e3fc8173ba3302e71"), 

  19. "classname" : "English", 

  20. "teacher" : "Mr AAA" 

  21. > db.class.find({classname:"English"}) 

  22. { "_id" : ObjectId("54fc562e3fc8173ba3302e71"), "classname" : "English", "teacher" : "Mr AAA" } 

  23. { "_id" : ObjectId("54fc56373fc8173ba3302e72"), "classname" : "English", "teacher" : "Mr ZZZ" } 

  24. { "_id" : ObjectId("54fc56413fc8173ba3302e73"), "classname" : "English", "teacher" : "Mr WWW" } 

  25. { "_id" : ObjectId("54fc564e3fc8173ba3302e74"), "classname" : "English", "teacher" : "Mr SSS" } 

  26. >

上述內(nèi)容就是Mongodb體系結(jié)構(gòu)與客戶端基本操作及注意細(xì)節(jié)有哪些,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI