【02】MongoDB使用入門 (全)


一、MongoDB簡介

1.MongoDB  

    ①MongoDB 是一個基於分布式 文件存儲的NoSQL數據庫。
    ②由C++語言編寫,運行穩定,性能高。 
    ③旨在為 WEB 應用提供可擴展的高性能數據存儲解決方案。 
    ④官方網址:https://www.mongodb.com/

2.MongoDB特點 

    ①MongoDB可以輕松地布置兩個活躍集群,但關系型不容易在兩台服務器上同時運行單個數據庫。
    ②MongoDB天然缺少對事物的支持。
    ③MongoDB並不提供主/主復制,但它支持分片。

3.Bson和Json 

    ①Bosn版本是Json的二進制格式,但並不意味着Bson占用的空間就比Json小的多。 
    ②繼續使用Bson的原因是因為MongoDB在設計上就是要求快速,而不是節省空間,如果處理數據的速度更快,存儲文檔時的一點開銷是完全可以接受的。 
    ③Bson更易於瀏覽(即遍歷),遍歷索引頁非常快,第二點是很容易將Bson數據快速轉化為編程語言的原生數據格式。

4.名詞

SQL術語/概念

MongoDB術語/概念

解釋/說明

database

database

數據庫

table

collection

數據庫表/集合

row

document

數據記錄行/文檔

column

field

數據字段/域

index

index

索引

table joins

 

表連接,MongoDB不支持

primary key

primary key

主鍵,MongoDB自動將_id字段設置為主鍵

5.MongoDB三要素

    ①數據庫:是一個集合的物理容器,一個數據庫中可以包含多個文檔,一個服務器通常有多個數據庫。 
    ②集合:類似於關系數據庫中的表,儲存多個文檔,結構不固定,如可以存儲如下文檔在一個集合中。

{'name':'guojing','gender':'男'}
{'name':'huangrong','age':18}
{'book':'shuihuzhuan','heros':'108'}

    ③文檔:就是一個對象,由鍵值對組成,是Json的擴展Bson格式。

{'name':'guojing','gender':'男'}

二、MongoDB安裝與管理

1.安裝 

    ①下載MongoDB的版本注意,兩點注意。 
        根據規則:偶數為穩定版,如1.6X,奇數為開發版,如1.7X。 
        32bit的MongoDB最大只能存放2G的數據,64bit就沒有限制。 
    ②到官網,選擇合適的版本下載 。
    ③解壓。

tar -zxvf mongodb-linux-x86_64-ubuntu1604-3.4.0.tgz

    ④移動到/usr/local/目錄下。

sudo mv -r mongodb-linux-x86_64-ubuntu1604-3.4.0/ /usr/local/mongodb

    ⑤將可執行文件添加到PATH路徑中。

export PATH=/usr/local/mongodb/bin:$PATH

2.管理 

    ①配置文件在/etc/mongod.conf,默認端口27017。 
    ②啟動。

sudo service mongod start

    ③停止。

sudo service mongod stop

    ④使用終端連接:mongo,這個shell就是mongodb的客戶端,同時也是一個js的編譯器。
    ⑤ GUI:robomongo,解壓后在bin目錄下找到運行程序。

三、數據庫操作

1.數據庫切換 

    ①查看當前數據庫名稱:db。
    ②查看所有數據庫名稱:show dbs,(列出所有在物理上存在的數據庫)。 
    ③切換數據庫:use 數據庫名稱,(如果數據庫不存在,則指向數據庫,但不創建,直到插入數據或創建集合時數據庫才被創建)。 
    ④默認的數據庫為test,如果沒有創建新的數據庫,集合將存放在test數據庫中。

2.數據庫刪除 

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

db.dropDatabase()

四、集合操作

1.集合創建 

db.createCollection(name,option)

    ①name是要創建集合的名稱。
    ②options是一個文檔,用於指定集合的配置。 
    ③選項參數是可選的,所以只需要到指定的集合名稱。
    ④不限制集合的大小。

db.createCollection(‘stu’)

    ⑤限制集合大小

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

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

2.查看當前數據庫的集合

show collections

3.刪除集合

db.集合名稱.drop()

五、數據類型

1. MongoDB中常用的數據類型 

    ①Object ID:文檔ID。
    ②String:字符串,最常用,必須是有效的UTF-8。 
    ③Boolean:存儲一個布爾值,true或false。 
    ④Integer:整數可以是32位或64位,這取決於服務器。 
    ⑤Double:存儲浮點值。 
    ⑥Arrays:數組或列表,多個值存儲到一個鍵。 
    ⑦Object:用於嵌入式的文檔,即一個值為一個文檔。
    ⑧Null:存儲Null值。 
    ⑨Timestamp:時間戳。
    ⑩Date:存儲當前日期或時間的UNIX時間格式。

2. Object id 

    ①每個文檔都有一個屬性,為_id,保證每個文檔的唯一性。 
    ②可以自己去設置_id插入文檔。
    ③如果沒有提供,那么MongoDB為每個文檔提供了一個獨特的_id,類型為objectID。 
    ④objectID是一個12字節的十六進制數。 
        前4個字節為當前時間戳。
        接下來3個字節的機器ID。 
        接下來的2個字節中MongoDB的服務進程id。 
        最后3個字節是簡單的增量值。

六、數據操作

1.插入 

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

db.集合名稱.insert(document)

2.簡單查詢

db.集合名稱.find()

3.更新

db.集合名稱.update(<query>,<update>,multi:<boolean>})

    ①參數query:查詢條件,類似sql語句update中where部分。
    ②參數update:更新操作符,類似sql語句update中set部分。 
    ③參數multi:可選,默認是false,表示只更新找到的第一條記錄,值為true表示把滿足條件的文檔全部更新。
    ④全文檔更新。

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

    ⑤指定屬性更新,通過操作符$set。

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

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

    ⑥修改多條匹配到的數據。

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

4.保存 

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

db.集合名稱.save(document)

5.刪除

db.集合名稱.remove( <query>,  { justOne: <boolean>})

    ①參數query:可選,刪除的文檔的條件。 
    ②參數justOne:可選,如果設為true或1,則只刪除一條,默認false,表示刪除多條。 
    ③只刪除匹配到的第一條。

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

    ④全部刪除。

db.stu.remove({})

七、數據查詢

1.基本查詢 

    ①方法find():查詢。

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

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

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

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

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

2.比較運算符

    ①等於,默認是等於判斷,沒有運算符。
    ②小於$lt。
    ③小於或等於$lte。
    ④大於$gt。
    ⑤大於或等於$gte。
    ⑥不等於$ne。
    ⑦查詢年齡大於或等於18的學生。

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

3.邏輯運算符

    ①查詢時可以有多個條件,多個條件之間需要通過邏輯運算符連接。
    ②邏輯與:默認是邏輯與的關系。
    ③查詢年齡大於或等於18,並且性別為1的學生。

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

    ④查詢年齡大於18,或性別為0的學生。

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

    ⑤查詢年齡大於18或性別為0的學生,並且學生的姓名為gj。

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

4.范圍運算符

    ①使用"$in","$nin" 判斷是否在某個范圍內。
    ②查詢年齡為18、28的學生。

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

5.支持正則表達式

    ①使用//或$regex編寫正則表達式。
    ②查詢姓黃的學生。

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

6.自定義查詢

    ①使用$where后面寫一個函數,返回滿足條件的數據。
    ②查詢年齡大於30的學生。

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

7. Limit

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

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

    ②參數NUMBER表示要獲取文檔的條數。
    ③如果沒有指定參數則顯示集合中的所有文檔。

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

8. skip

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

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

    ②參數NUMBER表示跳過的記錄條數,默認值為0。
    ③查詢從第3條開始的學生信息。

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

9.Limit與Skip

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

    ②查詢第5至8條數據(跳取)。

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

10. 投影

    ①在查詢到的返回結果中,只選擇必要的字段,而不是選擇一個文檔的整個字段。
    ②語法:參數為字段與值,值為1表示顯示,值為0不顯示。

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

    ③對於需要顯示的字段,設置為1即可,不設置即為不顯示。
    ④特殊:對於_id列默認是顯示的,如果不顯示需要明確設置為0。

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

11.排序

    ①方法sort(),用於對結果集進行排序。
    ②語法:db.集合名稱.find().sort({字段:1,...})。
        參數1為升序排列。
        參數-1為降序排列。
    ③根據性別降序,再根據年齡升序。

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

12.統計個數

    ①方法count()用於統計結果集中文檔條數。

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

        也可以與為

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

    ②統計男生人數。

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

    ③統計年齡大於20的男生人數。

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

13.消除重復

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

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

    ②查找年齡大於18的性別(去重)。

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

八、聚合 aggregate

1.聚合(aggregate)

    主要用於計算數據,類似sql中的sum()、avg()。

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

2.管道

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

 ps ajx | grep mongo

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

    1) 常用管道

        ①$group:將集合中的文檔分組,可用於統計結果。
        ②$match:過濾數據,只輸出符合條件的文檔。
        ③$project:修改輸入文檔的結構,如重命名、增加、刪除字段、創建計算結果。
        ④$sort:將輸入文檔排序后輸出。
        ⑤$limit:限制聚合管道返回的文檔數。
        ⑥$skip:跳過指定數量的文檔,並返回余下的文檔。
        ⑦$unwind:將數組類型的字段進行拆分。

    2) 表達式

        ①$sum:計算總和,$sum:1同count表示計數。
        ②$avg:計算平均值。
        ③$min:獲取最小值。
        ④$max:獲取最大值。
        ⑤$push:在結果文檔中插入值到一個數組中。
        ⑥$first:根據資源文檔的排序獲取第一個文檔數據。
        ⑦$last:根據資源文檔的排序獲取最后一個文檔數據。

3.$group

    將集合中的文檔分組,可用於統計結果。
    ①統計男生、女生的總人數。
        _id表示分組的依據,使用某個字段的格式為'$字段'。

db.stu.aggregate([{$group:{_id:'$gender',counter:{$sum:1}}}])

    ②求學生總人數、平均年齡。

db.stu.aggregate([{$group:{_id:null,counter:{$sum:1},avgAge:{$avg:'$age'} }}])

    ③統計學生性別及學生姓名。

db.stu.aggregate([{$group:{_id:'$gender',name:{$push:'$name'}}}])

    使用$$ROOT可以將文檔內容加入到結果集的數組中,代碼如下。

db.stu.aggregate([{$group:{_id:'$gender',name:{$push:'$$ROOT'}}}])

4.$match

    用於過濾數據,只輸出符合條件的文檔。

    ①查詢年齡大於20的學生。

db.stu.aggregate([{$match:{age:{$gt:20}}}])

    ②查詢年齡大於20的男生、女生人數。

db.stu.aggregate([{$match:{age:{$gt:20}}},{$group:{_id:'$gender',counter:{$sum:1}}}])

5.$project

    修改輸入文檔的結構,如重命名、增加、刪除字段、創建計算結果。
    ①查詢學生的姓名、年齡。

db.stu.aggregate([{$project:{_id:0,name:1,age:1}}])

    ②查詢男生、女生人數,輸出人數。

db.stu.aggregate([{$group:{_id:'$gender',counter:{$sum:1}}},{$project:{_id:0,counter:1}}])

6. $sort

    將輸入文檔排序后輸出。

    ①查詢學生信息,按年齡升序。

b.stu.aggregate([{$sort:{age:1}}])

    ②查詢男生、女生人數,按人數降序。

db.stu.aggregate([{$group:{_id:'$gender',counter:{$sum:1}}},{$sort:{counter:-1}}])

7. $limit,$skip

    限制聚合管道返回的文檔數。

    ①查詢2條學生信息。

db.stu.aggregate([{$limit:2}])

    跳過指定數量的文檔,並返回余下的文檔。
    ②查詢從第3條開始的學生信息。

db.stu.aggregate([{$skip:2}])

    ③統計男生、女生人數,按人數升序,取第二條數據。

db.stu.aggregate( [{$group:{_id:'$gender',counter:{$sum:1}}}, {$sort:{counter:1}},  {$skip:1}, {$limit:1}])

    注意順序:先寫skip,再寫limit。

8. $unwind

    將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值。
    語法1:對某字段值進行拆分。

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

    構造數據。

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

    查詢。

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

    語法2:對某字段值進行拆分。
    處理空數組、非數組、無字段、null情況。

db.inventory.aggregate([{ $unwind:{ path:'$字段名稱',   preserveNullAndEmptyArrays:<boolean>#防止數據丟失 }}])

    構造數據。

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:'$sizes',preserveNullAndEmptyArrays:true}}])

九、安全

1.超級管理員

    為了更安全的訪問mongodb,需要訪問者提供用戶名和密碼,於是需要在mongodb中創建用戶。
    采用了角色-用戶-數據庫的安全管理方式。
    常用系統角色如下:
        root:只在admin數據庫中可用,超級賬號,超級權限。
        Read:允許用戶讀取指定數據庫。
        readWrite:允許用戶讀寫指定數據庫。
    創建超級管理用戶。

use admindb.createUser({      
    user:'admin',      
    pwd:'123',      
    roles:[{role:'root',db:'admin'}]
})

2.啟用安全認證

    ①修改配置文件。

sudo vi /etc/mongod.conf

    ②啟用身份驗證
        注意:keys and values之間一定要加空格, 否則解析會報錯。

security: authorization: enabled

    ③重啟服務。

sudo service mongod stop
sudo service mongod start

    ④終端連接。

mongo -u 'admin' -p '123' --authenticationDatabase 'admin'

3.普通用戶管理

    ①使用超級管理員登錄,然后進入用戶管理操作。
    ②查看當前數據庫的用戶。

use test1show users

    ③創建普通用戶。

db.createUser({     
    user:'t1', pwd:'123', roles:[{role:'readWrite',db:'test1'}]
})

    ④終端連接。

mongo -u t1 -p 123 --authenticationDatabase test1

    ⑤切換數據庫,執行命令查看效果。

    ⑥修改用戶:可以修改pwd、roles屬性。

db.updateUser('t1',{pwd:'456'})

十、復制(副本集)

1.什么是復制

    ①復制提供了數據的冗余備份,並在多個服務器上存儲數據副本,提高了數據的可用性,並可以保證數據的安全性。
    ②復制還允許從硬件故障和服務中斷中恢復數據。

2.為什么要復制

    ①數據備份。
    ②數據災難恢復。
    ③讀寫分離。
    ④高(24* 7)數據可用性。
    ⑤無宕機維護。
    ⑥副本集對應用程序是透明。

3.復制的工作原理

    ①復制至少需要兩個節點A、B...。
    ②A是主節點,負責處理客戶端請求。
    ③其余的都是從節點,負責復制主節點上的數據。
    ④節點常見的搭配方式為:一主一從、一主多從。
    ⑤主節點記錄在其上的所有操作,從節點定期輪詢主節點獲取這些操作,然后對自己的數據副本執行這些操作,從而保證從節點的數據與主節點一致。
    ⑥主節點與從節點進行數據交互保障數據的一致性。

4.復制的特點

    ①N 個節點的集群。
    ②任何節點可作為主節點。
    ③所有寫入操作都在主節點上。
    ④自動故障轉移。
    ⑤自動恢復。

5.設置復制節點

    接下來的操作需要打開多個終端窗口,而且可能會連接多台ubuntu主機,會顯得有些亂,建議在xshell中實現。
    step1:創建數據庫目錄t1、t2。
        在Desktop目錄下演示,其它目錄也可以,注意權限即可。

mkdir t1mkdir t2

    step2:使用如下格式啟動mongod,注意replSet的名稱是一致的。

mongod --bind_ip 192.168.196.128 --port 27017 
--dbpath ~/Desktop/t1 --replSet 
rs0mongod --bind_ip 192.168.196.128 --port 27018 
--dbpath ~/Desktop/t2 --replSet rs0

    step3:連接主服務器,此處設置192.168.196.128:27017為主服務器。

mongo --host 192.168.196.128 --port 27017

    step4:初始化。

rs.initiate()

    step5:查看當前狀態。

rs.status()

    step6:添加復本集。

rs.add('192.168.196.128:27018')

    step7:連接第二個mongo服務。

mongo --host 192.168.196.128 --port 27018

    step8:向主服務器中插入數據。

use test1for(i=0;i<10;i++){ 
    db.t1.insert({_id:i})
}
db.t1.find()

    step9:在從服務器中插查詢。

        說明:如果在從服務器上進行讀操作,需要設置rs.slaveOk()。

rs.slaveOk()db.t1.find()

    其它說明。

        刪除從節點。

rs.remove('192.168.196.128:27018')

    關閉主服務器后,再重新啟動,會發現原來的從服務器變為了主服務器,新啟動的服務器(原來的從服務器)變為了從服務器。

十一、備份和恢復

1.備份

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

2.恢復

mongorestore -h dbhost -d dbname --dir dbdirectory

    -h:服務器地址。
    -d:需要恢復的數據庫實例。
    -dir:備份數據所在位置。

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

十二、與python交互

1.官方文檔

    http://api.mongodb.org/python/current/tutorial.html

2.安裝python包

    1) 進入虛擬環境

sudo pip install pymongo

    2) 或源碼安裝

python setup.py

    3) 引入包pymongo

import pymongo

    4) 連接,創建客戶端

client = pymongo.MongoClient("localhost", 27017)

    5) 獲得數據庫test1

db = client.test1

    6) 獲得集合stu

stu = db.stu

    7) 添加文檔

s1 = {name:'gj',age:18}
s1_id = stu.insert_one(s1).inserted_id

    8) 查找一個文檔

s2 = stu.find_one()

    9) 查找多個文檔1

for cur in stu.find():      
    print cur

    10) 查找多個文檔2

cur = stu.find()cur.next()cur.next()cur.next()

    11) 獲取文檔個數

print stu.count()


免責聲明!

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



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