在網(wǎng)絡(luò)交互的過程中,不僅會有數(shù)據(jù)的傳遞,也會有新數(shù)據(jù)的產(chǎn)生。比如我們目前的網(wǎng)站登錄注冊項目,在用戶注冊后,我們只是把數(shù)據(jù)添加到了服務(wù)器的內(nèi)存中,但是程序一旦關(guān)閉或者重啟,內(nèi)存中的數(shù)據(jù)就消失了,服務(wù)器會恢復(fù)到最初的樣子,那注冊的用戶數(shù)據(jù)也就沒有了。這對于網(wǎng)站來講,是不可接受的。那么如何解決這個問題呢?
什么是數(shù)據(jù)庫
在網(wǎng)絡(luò)交互的過程中,不僅會有數(shù)據(jù)的傳遞,也會有新數(shù)據(jù)的產(chǎn)生。比如我們目前的網(wǎng)站登錄注冊項目,在用戶注冊后,我們只是把數(shù)據(jù)添加到了服務(wù)器的內(nèi)存中,但是程序一旦關(guān)閉或者重啟,內(nèi)存中的數(shù)據(jù)就消失了,服務(wù)器會恢復(fù)到最初的樣子,那注冊的用戶數(shù)據(jù)也就沒有了。這對于網(wǎng)站來講,是不可接受的。那么如何解決這個問題呢?
服務(wù)器程序,就像是我們大腦的記憶,并不是長久的,一旦重啟,就會失憶。俗?話說,好記性不如爛筆頭。因此最好的辦法,就是把數(shù)據(jù)記錄并保存下來。
在早期的網(wǎng)站中,通過把數(shù)據(jù)寫入到文件中來進(jìn)行保存,即便電腦關(guān)閉重啟,文件也不會消失。但慢慢的又發(fā)現(xiàn)了問題,當(dāng)文件存儲內(nèi)容過多的時候,很難找到我們想要的那條數(shù)據(jù),而且,讀取文件也是一個非常耗時的過程。
為了能夠更好的存儲數(shù)據(jù),數(shù)據(jù)庫應(yīng)運(yùn)而生,在本系列課程中,我們要使用的數(shù)據(jù)庫是MongoDB。
圖書館是一個存儲圖書的地方,糧倉是用來存儲糧食的。數(shù)據(jù)庫,顧名思義,就是專門用來存儲數(shù)據(jù)的倉庫。存儲在數(shù)據(jù)庫中的數(shù)據(jù),能夠長期的保存,并且易于查找。
在數(shù)據(jù)庫中,數(shù)據(jù)不是雜亂無章的,它們會放在一個一個的小盒子里,在MongoDB中這些盒子就稱為集合。一個數(shù)據(jù)庫中可以有多個集合,而集合中存儲的是一條一條的數(shù)據(jù)。
MongoDB簡介
NoSQL(NoSQL = Not Only SQL ),意即"不僅僅是SQL"。
在現(xiàn)代的計算系統(tǒng)上每天網(wǎng)絡(luò)上都會產(chǎn)生龐大的數(shù)據(jù)量。
這些數(shù)據(jù)有很大一部分是由關(guān)系數(shù)據(jù)庫管理系統(tǒng)(RDBMS)來處理。 1970年 E.F.Codd's提出的關(guān)系模型的論文 "A relational model of data for large shared data banks",這使得數(shù)據(jù)建模和應(yīng)用程序編程更加簡單。
通過應(yīng)用實踐證明,關(guān)系模型是非常適合于客戶服務(wù)器編程,遠(yuǎn)遠(yuǎn)超出預(yù)期的利益,今天它是結(jié)構(gòu)化數(shù)據(jù)存儲在網(wǎng)絡(luò)和商務(wù)應(yīng)用的主導(dǎo)技術(shù)。
NoSQL 是一項全新的數(shù)據(jù)庫革命性運(yùn)動,早期就有人提出,發(fā)展至2009年趨勢越發(fā)高漲。NoSQL的擁護(hù)者們提倡運(yùn)用非關(guān)系型的數(shù)據(jù)存儲,相對于鋪天蓋地的關(guān)系型數(shù)據(jù)庫運(yùn)用,這一概念無疑是一種全新的思維的注入。
- 易擴(kuò)展: NoSQL數(shù)據(jù)庫種類繁多, 但是一個共同的特點(diǎn)都是去掉關(guān)系數(shù)據(jù)庫的關(guān)系型特性。 數(shù)據(jù)之間無關(guān)系, 這樣就非常容易擴(kuò)展
- 大數(shù)據(jù)量,高性能: NoSQL數(shù)據(jù)庫都具有非常高的讀寫性能, 尤其在大數(shù)據(jù)量下表現(xiàn)優(yōu)秀。 這得益于它的非關(guān)系性,數(shù)據(jù)庫的結(jié)構(gòu)簡單
- 靈活的數(shù)據(jù)模型: NoSQL無需事先為要存儲的數(shù)據(jù)建立字段, 隨時可以存儲自定義的數(shù)據(jù)格式。 而在關(guān)系數(shù)據(jù)庫中, 增刪字段是一件非常麻煩的事情。
MongoDB 是由C++語言編寫的,是一個基于分布式文件存儲的開源數(shù)據(jù)庫系統(tǒng)。
在高負(fù)載的情況下,添加更多的節(jié)點(diǎn),可以保證服務(wù)器性能。
MongoDB 旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲解決方案。
MongoDB 將數(shù)據(jù)存儲為一個文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對組成。MongoDB 文檔類似于 JSON 對象。字段值可以包含其他文檔,數(shù)組及文檔數(shù)組。
- 安裝:sudo apt install -y mongodb
- 默認(rèn)端口:27017
- 默認(rèn)配置文件的位置:/etc/mongod.conf
- 默認(rèn)日志的位置:/var/log/mongodb/mongod.log
- 查看日志:grep -v '#' /etc/mongodb.conf
創(chuàng)建和刪除數(shù)據(jù)庫
- 創(chuàng)建/切換數(shù)據(jù)庫:use DATABASE_NAME,如果數(shù)據(jù)庫不存在,則創(chuàng)建數(shù)據(jù)庫,否則切換到指定數(shù)據(jù)庫。沒有切換數(shù)據(jù)庫的情況下默認(rèn)使用test數(shù)據(jù)庫。
- 查看所有數(shù)據(jù)庫:show dbs / show databases
- 刪除當(dāng)前的數(shù)據(jù)庫:db.dropDatabase()
創(chuàng)建和刪除集合
- 創(chuàng)建集合:db.createCollection(name,options)db.createCollection('stu', { cApped:true, size:200, max:2} )參數(shù)capped:默認(rèn)值為false表示不設(shè)置上限,值為true表示設(shè)置上限參數(shù)size:集合所占用的字節(jié)數(shù)。 當(dāng)capped值為true時,需要指定此參數(shù),表示上限大小,當(dāng)文檔達(dá)到上限時, 會將之前的數(shù)據(jù)覆蓋,單位為字節(jié)參數(shù)max:文檔最大數(shù)量
- 查看集合:show collections
- 刪除集合:db.集合名稱.drop()
- 檢查集合是否設(shè)定上限: db.集合名.isCapped()
啟動方式:測試啟動
- 啟動: sudo service mongod start
- 停止: sudo service mongod stop
- 重啟: sudo service mongod restart
啟動失敗:Failed to start mongod.service: Unit mongod.service not found.
- 解決方案
- 創(chuàng)建配置文件:sudo vim /etc/systemd/system/mongodb.service
- [Unit] Descriptinotallow=High-performance, schema-free document-oriented database After.NETwork.target [Service] User=mongodb ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf [Install] WantedBy=multi-user.target
- 啟動服務(wù)
- sudo systemctl start mongodb
- sudo systemctl status mongodb
- 檢測是否啟動成功:ps aux | grep mongod
- 永久啟動:sudo systemctl enable mongodb
生產(chǎn)環(huán)境正式的啟動方式
啟動: sudo mongod [--auth --dbpath=dbpath --logpath=logpath --append --fork] [-–f logfile ]
- 只以 sudo mongod 命令啟動時,默認(rèn)將數(shù)據(jù)存放在了 /data/db 目錄下,需要手動創(chuàng)建
- --dbpath: 指定數(shù)據(jù)庫的存放路徑
- --logpath: 指定日志的存放路徑
- --append: 或--logappend 設(shè)置日志的寫入形式為追加模式
- --fork: 或-fork 開啟新的進(jìn)程運(yùn)行mongodb服務(wù)
- --f: 或-f 配置文件路徑(可以將上述配置信息寫入文件然后通過該文件中的參數(shù)進(jìn)行加載啟動)
- --auth: 以權(quán)限認(rèn)證的方式啟動
配置文件啟動
sudo mongod -f mogo_start.cfg
dbpath=/home/cat/data/db
logpath=/home/cat/data/mongodb.log
logappend=true
fork=true
mongoDB支持的數(shù)據(jù)類型
mongoDB文檔存儲是使用BSON類型,BSON(BSON short for Binary JSON, is a binary-encoded serialization of JSON-like documents)是二進(jìn)制序列化的形式。類如JSON,同樣支持內(nèi)嵌各種類型。
MongoDB的單個實例可以容納多個獨(dú)立的數(shù)據(jù)庫,每一個都有自己的集合和權(quán)限,不同的數(shù)據(jù)庫也放置在不同的文件中
下表為MongoDB 常用的幾種數(shù)據(jù)類型:
數(shù)據(jù)類型 |
描述 |
String |
字符串。存儲數(shù)據(jù)常用的數(shù)據(jù)類型。在 MongoDB 中,UTF-8 編碼的字符串才是合法的。 |
Integer |
整型數(shù)值。用于存儲數(shù)值。根據(jù)你所采用的服務(wù)器,可分為 32 位或 64 位。 |
Boolean |
布爾值。用于存儲布爾值(真/假)。 |
Double |
雙精度浮點(diǎn)值。用于存儲浮點(diǎn)值。 |
Array |
用于將數(shù)組或列表或多個值存儲為一個鍵。 |
Timestamp |
時間戳。記錄文檔修改或添加的具體時間。 |
Object |
用于內(nèi)嵌文檔。 |
Null |
用于創(chuàng)建空值。 |
Date |
日期時間。用 UNIX 時間格式來存儲當(dāng)前日期或時間。你可以指定自己的日期時間:創(chuàng)建 Date 對象,傳入年月日信息。 |
Object ID |
對象 ID。用于創(chuàng)建文檔的 ID?! ?每個文檔都有) |
ObjectId
ObjectId 類似唯一主鍵,可以很快的去生成和排序,包含 12 bytes,含義是:
- 前 4 個字節(jié)表示創(chuàng)建 unix時間戳,格林尼治時間 UTC 時間,比北京時間晚了 8 個小時
- 接下來的 3 個字節(jié)是機(jī)器標(biāo)識碼
- 緊接的兩個字節(jié)由進(jìn)程 id 組成 PID
- 最后三個字節(jié)是隨機(jī)數(shù)
增刪改查
- 插入數(shù)據(jù):db.集合名稱.insert(document)
- db.stu.insert({name:'xiaoming', gender:true, age:10, class:'2年4班', score:100})
- db.stu.insert([{ name:'xiaomei', gender:false, age:12, class:'2年3班', score:90 },{ name:'xiaohong', gender:false, age:12, class:'2年3班', score:96 },{ name:'Jack', gender:false, age:12, class:'2年2班', score:98 },{ name:'Allen', gender:true, age:12, class:'2年3班', score:90 }])
- 插文檔時,如果不指定_id參數(shù),MongoDB會為文檔自動分配一個唯一的ObjectId
- mongodb的保存:db.集合名稱.save(document)
如果文檔的_id已經(jīng)存在則修改,如果_id不存在則添加
- mongodb的查詢
1.db.集合名稱.find({條件文檔})
2.方法findOne():查詢,只返回第一個db.集合名稱.findOne({條件文檔})
3.方法pretty(): 將結(jié)果格式化;不能和findOne()一起使用!db.集合名稱.find({條件文檔}).pretty()
- 比較運(yùn)算符
1.等于: 默認(rèn)是等于判斷, 沒有運(yùn)算符
2.小于:$lt (less than)
3.小于等于:$lte (less than equal)
4.大于:$gt (greater than)
5.大于等于:$gte
6.不等于:$ne
- 邏輯運(yùn)算符
1.and:在json中寫多個條件即可
2.or:使用$or, 值為數(shù)組, 數(shù)組中每個元素為json
3.范圍運(yùn)算符:使用$in, $nin 判斷數(shù)據(jù)是否在某個數(shù)組內(nèi)
- 使用$regex編寫正則表達(dá)式:db.stu.find({name:{$regex:'^張'}})
- 自定義查詢
1.shell 是一個js的執(zhí)行環(huán)境
2.使用$where寫一個函數(shù), 返回滿足條件的數(shù)據(jù)
3.db.stu.find({ $where:function() { return this.age + 10>= 18; } })
- skip和limit分頁查詢:db.stu.find().skip((page-1)*num).limit(x)
- 投影,在查詢到的返回結(jié)果中, 只選擇必要的字段
1.db.集合名稱.find({},{字段名稱:1,...})
2.參數(shù)為字段與值, 值為1表示顯示, 值為0不顯
3.特別注意:對于_id列默認(rèn)是顯示的, 如果不顯示需要明確設(shè)置為0對于其他不顯示的字段不能設(shè)置為0db.stu.find({},{_id:0,name:1,gender:1})
- 排序:db.集合名稱.find().sort({字段:1,...})
1.參數(shù)1為升序排列
2.參數(shù)-1為降序排列
3.db.stu.find().sort({score:-1,age:1})
- 統(tǒng)計個數(shù)
1.db.集合名稱.estimated_document_count()
2.db.集合名稱.count_documents({條件})
- 去重:db.集合名稱.distinct(字段,{條件})
- 更新:db.集合名稱.update({query}, {update}, {multi: boolean})
1.參數(shù)query:查詢條件
2.參數(shù)update:更新操作符
3.參數(shù)multi:可選,默認(rèn)是false,表示只更新找到的第一條數(shù)據(jù),值為true表示把滿足條件的數(shù)據(jù)全部更新multi參數(shù)必須和$set一起使用!
- 刪除:db.集合名稱.remove({query}, {justOne: boolean})
1.參數(shù)query:可選,刪除的?檔的條件
2.參數(shù)justOne:可選, 如果設(shè)為true或1,則只刪除一條,默認(rèn)false,表示刪除全部