MongoDB學習總結(一)

1. MongoDB 簡介

MongoDB是一個可擴展的高性能,開源,模式自由,面向文檔的NoSQL,基于分布式文件存儲由 C++ 語言編寫,設計之初旨在為 WEB 應用提供可擴展的高性能數據存儲解決方案。

2. MongoDB特點

模式自由 :可以把不同結構的文檔存儲在同一個數據庫里

面向集合的存儲:適合存儲 JSON風格文件的形式,

完整的索引支持:對任何屬性可索引,

復制和高可用性:支持服務器之間的數據復制,支持主-從模式及服務器之間的相互復制。復制的主要目的是提供冗余及自動故障轉移。

自動分片:支持水平的數據庫集群,可動態添加額外的機器。

豐富的查詢:支持豐富的查詢表達方式,查詢指令使用JSON形式的標記,可輕易查詢文檔中的內嵌的對象及數組。

快速就地更新:查詢優化器會分析查詢表達式,并生成一個高效的查詢計劃。

高效的傳統存儲方式:支持二進制數據及大型對象(如圖片等...)。

3. MongoDB與SQL區別

MongoDB與SQL區別??

4. 適用場景

網站數據: 適合實時的插入,更新與查詢,并具備網站實時數據存儲所需的復制及高度伸縮性。

緩存: 由于性能很高,也適合作為信息基礎設施的緩存層。在系統重啟之后,搭建的持久化緩存可以避免下層的數據源過載。

大尺寸、低價值的數據: 使用傳統的關系數據庫存儲一些數據時可能會比較貴,在此之前,很多程序員往往會選擇傳統的文件進行存儲。

高伸縮性的場景: 非常適合由數十或者數百臺服務器組成的數據庫。

用于對象及JSON數據的存儲: MongoDB的BSON數據格式非常適合文檔格式化的存儲及查詢。

5. MongoDB的安裝與使用

1. MongoDB官網安裝包下載地址:http://www.mongodb.org/downloads

MongoDB安裝文檔:https://docs.mongodb.com/getting-started/shell/installation/

Ubuntu下安裝MongoDB:

python@ubuntu:~$ sudo apt-get install mongodb

注意:使用MongoDB,需要先啟動服務端,再使用客戶端連接數據庫。

2. 服務端

MongoDB 默認的存儲數據目錄為 /data/db,默認端口27017

服務的命令為mongod,可以通過help查看所有參數

python@ubuntu:~$ mongod --help

相關文件存放路徑:默認各個文件存放路徑如下所示:

可執行文件存放路徑:/usr/bin/mongod和/usr/bin/mongo

數據庫文件存放路徑:/data/db

日志文件存放路徑:/var/log/mongodb/mongod.log

配置文件存放路徑:/etc/mongod.conf

3. 啟動注意事項

1. 首次啟動:

啟動MongoDB服務:sudo mongod

報出如下錯誤,表示默認的存儲數據目錄 /data/db 不存在:

[initandlisten] exception in initAndListen: 29 Data directory /data/db not found., terminating

創建 /data目錄和 /data/db 目錄,并指定 讀/寫/執行 權限

python@ubuntu:~$ sudo mkdir -p /data/db

python@ubuntu:~$ sudo chmod777/data/db

2. 再次啟動:

再次啟動MongoDB服務:sudo mongod

啟動成功,但是可能會有三個warning的警告

Warning 1:

[initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.[initandlisten] ** We suggest setting it to 'never'[initandlisten][initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.[initandlisten] ** We suggest setting it to 'never'

Linux的內存分配默認由內核動態分配,而不是由程序自行管理。而MongoDB對內存占用有那么點...嚴重,所以為了防止MongoDB占用內存過大而被內核"管理",官方推薦關閉動態分配。

默認"always"表示允許動態分配,對應的"never"就是不允許,所以我們將這兩個文件內容修改為"naver"后就沒有warning了。

# Ctrl + c 退出 MongoDB 數據庫服務# 然后進入 root 用戶下,執行修改命令python@ubuntu:~$ sudo su[sudo] python 的密碼: root@ubuntu:~# sudo echo "never" > /sys/kernel/mm/transparent_hugepage/enabledroot@ubuntu:~# sudo echo "never" >? /sys/kernel/mm/transparent_hugepage/defrag

實際上,除非網站DBA對數據庫性能有極限要求,在通常情況下系統動態分配的內存頁大小足夠我們正常使用,而且更能優化整個系統,所以一般不必理會這個warning。而且這樣只是臨時修改Linux內核的設置,在Linux服務器重啟后則會失效。

Warning 2:

[initandlisten] ** WARNING: soft rlimits too low.rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.

這個WARNING(如果有的話)含義為: 表示默認分配給MongoDB的進程和文件數量限制過低,需要重新分配值:

mongodb當前限制:1024 processes, 64000 files

mongodb建議要求:processes = 0.5*files=32000(至少)

咱們學習階段默認用不著這么多的進程和文件,所以也可以不必理會。

# 打開 相關配置文件:root@ubuntu:~# vi /etc/security/limits.conf# 在打開的 文件最下方,添加,然后保存退出mongod? soft? nofile64000mongod? hard? nofile64000mongod? soft? nproc32000mongod? hard? nproc32000

Warning 3:

[initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.

意思是我們在用root權限做這些事,理論上是不安全的。我們可以通過附加--auth參數,來使用用戶認證來處理這個情況,這個后面會講到。

3. 再再次啟動:

再再次啟動MongoDB服務:sudo mongod

啟動后查看進程,以確定是否啟動成功

python@ubuntu:~$ ps aux | grep mongod

如果進程中沒有mongod的項則沒有啟動成功,可以通過查看日志來確定錯誤原因,默認日志文件為/var/log/mongodb/mongod.log,最新的信息在最后面顯示。

4. 客戶端

客戶端命令為mongo,可以通過help查看所有參數。

這個shell即是mongodb的客戶端,用來對MongoDB進行操作和管理的交互式環境。

python@ubuntu:~$ mongo --help

終端退出連接

> exit

6. MongoDB數據庫命令

1、連接成功后,默認使用test數據庫

查看當前數據庫名稱

db

2、查看所有數據庫名稱,列出所有在物理上存在的數據庫

show dbs

3、切換數據庫,如果數據庫不存在也并不創建,直到插入數據或創建集合時數據庫才被創建

use 數據庫名稱

4、刪除當前指向的數據庫,如果數據庫不存在,則什么也不做

db.dropDatabase()

7. MongoDB集合命令

創建語法如下:

name是要創建的集合的名稱

options是一個文檔,用于指定集合的配置,選項??參數是可選的,所以只需要到指定的集合名稱

可以不手動創建集合,向不存在的集合中第一次加入數據時,集合會被創建出來

db.createCollection(name, options)

例1:不限制集合大小

db.createCollection("stu")

例2:限制集合大小,后面學會插入語句后可以查看效果

參數capped:默認值為false表示不設置上限,值為true表示設置上限

參數size:當capped值為true時,需要指定此參數,表示上限大小,當文檔達到上限時,會將之前的數據覆蓋,單位為字節

db.createCollection("sub", { capped : true, size : 10 } )

查看當前數據庫的集合

show collections

刪除命令

db.集合名稱.drop()

8.?MongoDB文檔命令

1.MongoDB的數據類型

Object ID:文檔ID

String:? 字符串,最常用,必須是有效的UTF-8

Boolean:? 存儲一個布爾值,true或false

Integer:? 整數可以是32位或64位,這取決于服務器

Double:? 存儲浮點值

Arrays:? 數組或列表,多個值存儲到一個鍵

Object:? 用于嵌入式的文檔,即一個值為一個文檔

Null:? ? 存儲Null值

Timestamp:時間戳,表示從1970-1-1到現在的總秒數

Date:? ? 存儲當前日期或時間的UNIX時間格式

創建日期語句如下

注意:參數的格式為YYYY-MM-DD

new Date('2015-11-11')

object id

每個文檔都有一個屬性,為_id,保證每個文檔的唯一性

可以自己去設置_id插入文檔

如果沒有提供,那么MongoDB為每個文檔提供了一個獨特的_id,類型為objectID

objectID是一個12字節的十六進制數:

前4個字節為當前時間戳

接下來3個字節為機器ID

接下來的2個字節為MongoDB的服務進程id

最后3個字節為簡單的增量值

2.?MongoDB的數據增刪改查

1、插入語法:

db.集合名稱.insert(document)

插入文檔時,如果不指定_id參數,MongoDB會為文檔分配一個唯一的ObjectId

例1

db.stu.insert({name:'gj',gender:1})

例2

s1={_id:'2015111',name:'hr'}

s1.gender=0

db.stu.insert(s1)

2、更新語法:

db.集合名稱.update(

? ? <query>,

? ? <update>,

?????{multi:boolean<>}

????)

參數query:查詢條件,類似sql語句update中where部分

參數update:更新操作符,類似sql語句update中set部分

參數multi:可選,默認是false,表示只更新找到的第一條記錄,

值為true表示把滿足條件的文檔全部更新

例1:全文檔更新

db.stu.update({name:'hr'},{name:'mnc'})

例2:指定屬性更新,通過操作符$set

db.stu.insert({name:'hr',gender:0})

db.stu.update({name:'hr'},{$set:{name:'hys'}})

例3:修改多條匹配到的數據

db.stu.update({},{$set:{gender:0}},{multi:true})

3、保存語法:

db.集合名稱.save(document)

如果文檔的_id已經存在則修改,如果文檔的_id不存在則添加

例1

db.stu.save({_id:'20160102','name':'yk',gender:1})

例2

db.stu.save({_id:'20160102','name':'wyk'})

4、刪除語法:

db.集合名稱.remove(

? ? query,

????{

????justOne:

????})

參數query:可選,刪除的文檔的條件

參數justOne:可選,如果設為true或1,則只刪除一條,默認false,表示刪除多條

例1:只刪除匹配到的第一條

db.stu.remove({gender:0},{justOne:true})

例2:全部刪除

db.stu.remove({})

9. MongoDB數據查詢

1、基本查詢:

方法find():查詢

db.集合名稱.find({條件文檔})

方法findOne():查詢,只返回第一個

db.集合名稱.findOne({條件文檔})

方法pretty():將結果格式化

db.集合名稱.find({條件文檔}).pretty()

2、比較運算符:

等于,默認是等于判斷,沒有運算符

小于$lt

小于或等于$lte

大于$gt

大于或等于$gte

不等于$ne

例1:查詢名稱等于'zhangsan'的學生

db.stu.find({name:'zhangsan'})

例2:查詢年齡大于或等于18的學生

db.stu.find({age:{$gte:18}})

3、邏輯運算符:

查詢時可以有多個條件,多個條件之間需要通過邏輯運算符連接

邏輯與:默認是邏輯與的關系

例1:查詢年齡大于或等于18,并且性別為true的學生

db.stu.find({age:{$gte:18},gender:true})

邏輯或:使用$or,值為數組,數組中每個元素為json

例2:查詢年齡大于18,或性別為false的學生

db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})

and和or一起使用

例3:查詢年齡大于18或性別為true的學生,并且學生的姓名為gj

db.stu.find({$or:[{age:{$gte:18}},{gender:true}],name:'gj'})

4、范圍運算符:

使用"$in","$nin" 判斷是否在某個范圍內

例1:查詢年齡為18、28的學生

db.stu.find({age:{$in:[18,28]}})

5、支持正則表達式:

mongodb提供的終端shell,同時也是一個js的執行器,可以編寫js的代碼和函數

使用//或$regex編寫正則表達式

例1:查詢姓黃的學生

db.stu.find({name:/^黃/})

db.stu.find({name:{$regex:'^黃'}}})

6、自定義查詢:

使用$where后面寫一個函數(js函數),返回滿足條件的數據

例1:查詢年齡大于30的學生

db.stu.find({$where:function(){return this.age>30;}})

10. MongoDB中limit與skip的應用

limit

方法limit():用于讀取指定數量的文檔

語法:

db.集合名稱.find().limit(NUMBER)

參數NUMBER表示要獲取文檔的條數

如果沒有指定參數則顯示集合中的所有文檔

例1:查詢2條學生信息

db.stu.find().limit(2)

skip

方法skip():用于跳過指定數量的文檔

語法:

db.集合名稱.find().skip(NUMBER)

參數NUMBER表示跳過的記錄條數,默認值為0

例1:查詢從第3條開始的學生信息

db.stu.find().skip(2)

方法limit()和skip()可以一起使用,不分先后順序

創建數據集

for(i=0;i<15;i++){db.t1.insert({_id:i})}

查詢第5至8條數據

db.stu.find().limit(4).skip(5)

db.stu.find().skip(5).limit(4)

11.?MongoDB投影

定義:在查詢到的返回結果中,只選擇必要的字段,而不是選擇一個文檔的整個字段

如:一個文檔有5個字段,需要顯示只有3個,投影其中3個字段即可

語法:

參數為字段與值,值為1表示顯示,值為0不顯示

db.集合名稱.find({},{字段名稱:1,...})

對于需要顯示的字段,設置為1即可,不設置即為不顯示

特殊:對于_id列默認是顯示的,如果不顯示需要明確設置為0

例1

db.stu.find({},{name:1,gender:1})

例2

db.stu.find({},{_id:0,name:1,gender:1})

12.?MongoDB排序

定義:方法sort(),用于對結果集進行排序

語法

db.集合名稱.find().sort({字段:1,...})

參數1為升序排列

參數-1為降序排列

例1:根據性別降序,再根據年齡升序

db.stu.find().sort({gender:-1,age:1})

13.?MongoDB統計個數

定義:方法count()用于統計結果集中文檔條數

語法

db.集合名稱.find({條件}).count()

也可以與為

db.集合名稱.count({條件})

例1:統計男生人數

db.stu.find({gender:true}).count()

例2:統計年齡大于20的男生人數

db.stu.count({age:{$gt:20},gender:true})

14.?MongoDB消除重復

方法distinct()對數據進行去重

語法

db.集合名稱.distinct('去重字段',{條件})

例:查找年齡大于18的學生,來自哪些省份

db.stu.distinct('hometown',{age:{$gt:18}})

15.?MongoDB聚合 aggregate

定義:聚合(aggregate)主要用于計算數據,類似sql中的sum()、avg()

語法:db.集合名稱.aggregate([{管道:{表達式}}])

管道:管道在Unix和Linux中一般用于將當前命令的輸出結果作為下一個命令的輸入

ps ajx | grep mongo

在mongodb中,管道具有同樣的作用,文檔處理完畢后,通過管道進行下一次處理

常用管道

$group:將集合中的文檔分組,可用于統計結果

$match:過濾數據,只輸出符合條件的文檔

$project:修改輸入文檔的結構,如重命名、增加、刪除字段、創建計算結果

$sort:將輸入文檔排序后輸出

$limit:限制聚合管道返回的文檔數

$skip:跳過指定數量的文檔,并返回余下的文檔

$unwind:將數組類型的字段進行拆分

表達式:處理輸入文檔并輸出

語法:表達式:'$列名'

常用表達式

$sum:? 計算總和,$sum:1同count表示計數

$avg:? 計算平均值

$min:? 獲取最小值

$max:? 獲取最大值

$push:? 在結果文檔中插入值到一個數組中

$first: 根據資源文檔的排序獲取第一個文檔數據

$last:? 根據資源文檔的排序獲取最后一個文檔數據

16.?unwind

將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值

語法1

對某字段值進行拆分

db.集合名稱.aggregate([{$unwind:'$字段名稱'}])

構造數據

db.t2.insert({_id:1,item:'t-shirt',size:['S','M','L']})

查詢

db.t2.aggregate([{$unwind:'$size'}])

語法2

對某字段值進行拆分

處理空數組、非數組、無字段、null情況

屬性preserveNullAndEmptyArrays值為false表示丟棄屬性值為空的文檔

屬性preserveNullAndEmptyArrays值為true表示保留屬性值為空的文檔

db.inventory.aggregate([{

$unwind:{

path:'$字段名稱',

preserveNullAndEmptyArrays:#防止數據丟失

}

}])

構造數據

db.t3.insert([

{ "_id" : 1, "item" : "a", "size": [ "S", "M", "L"] },

{ "_id" : 2, "item" : "b", "size" : [ ] },

{ "_id" : 3, "item" : "c", "size": "M" },

{ "_id" : 4, "item" : "d" },

{ "_id" : 5, "item" : "e", "size" : null }

])

使用語法1查詢

db.t3.aggregate([{$unwind:'$size'}])

查看查詢結果,發現對于空數組、無字段、null的文檔,都被丟棄了

問:如何能不丟棄呢?

答:使用語法2查詢

db.t3.aggregate([{$unwind:{path:'$size',preserveNullAndEmptyArrays:true}}])

17.?MongoDB索引

在mysql中已經學習了索引,并知道索引對于查詢速度的提升

mongodb也支持索引,以提升查詢速度

步驟一:創建大量數據

在命令行中執行如下代碼,向集合中插入10萬條文檔

注意:不要在圖形界面中執行,因為軟件原因無法插入10萬條數據就會中斷執行

for(i=0;i<100000;i++){

db.t1.insert({name:'test'+i,age:i})

}

步驟二:數據查找性能分析

查找姓名為'test10000'的文檔

db.t1.find({name:'test10000'})

使用explain()命令進行查詢性能分析

db.t1.find({name:'test10000'}).explain('executionStats')

其中的executionStats下的executionTimeMillis表示整體查詢時間,單位是毫秒

性能分析結果如下圖,由于機器的配置原因這個時間也會不同

索引前

性能分析結果

步驟三:建立索引

創建索引

1表示升序,-1表示降序

db.集合.ensureIndex({屬性:1})

db.t1.ensureIndex({name:1})

步驟四:對索引屬性查詢

執行上面的同樣的查詢,并進行查詢性能分析

db.t1.find({name:'test10000'}).explain('executionStats')

性能分析結果如下圖

索引后:

索引的命令

建立唯一索引,實現唯一約束的功能

db.t1.ensureIndex({"name":1},{"unique":true})

聯合索引,對多個屬性建立一個索引,按照find()出現的順序

db.t1.ensureIndex({name:1,age:1})

查看文檔所有索引

db.t1.getIndexes()

刪除索引

db.t1.dropIndex('索引名稱')

18.?MongoDB 備份與恢復

備份

語法:

mongodump -h dbhost -d dbname -o dbdirectory

-h:服務器地址,也可以指定端口號

-d:需要備份的數據庫名稱

-o:備份的數據存放位置,此目錄中存放著備份出來的數據

例1

sudo mkdir test1bak

sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak

恢復

語法:

mongorestore -h dbhost -d dbname --dir dbdirectory

-h:服務器地址

-d:需要恢復的數據庫實例

--dir:備份數據所在位置

例1

mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容