Node.js日記:數據庫(MongoDB)

爲什麼使用數據庫

原本存儲數據的方式比如使用 Excel,不適合存儲大量數據,也不適合需求變得複雜的環境。Excel 的儲存量有限,訪問速度及處理速度在數據量大時也是短板,且擴展性(兼容性)是遠遠不如數據庫的。

數據庫相關概念

數據庫(DB)Database:是按照數據結構來組織、存儲和管理數據的倉庫。

數據庫管理系統(DBMS):是專門用於管理數據庫的計算機系統軟件。

數據庫管理系統能夠爲數據庫提供數據的定義、建立、維護、查詢和統計等操作功能,並完成對數據完整性、安全性進行控制的功能。

DBA:數據庫是一門學科,專門做數據庫運維的人叫 Database Administrator。

數據庫分類

分爲兩大類:關係型數據庫和非關係數據庫。

- 關係型數據庫是由多張能互相聯接的二維行列表格組成的數據庫。典型的代表:MySQL、PostgreSQL、SQlServer、Oracle、DB2 等。
- NoSQL(Not Only SQL),非關係型數據庫,典型的代表:MongoDB,Redis,HBase,CouchDB 等。

NoSQL

NoSQL 分類:

- 鍵值(Key-Value)存儲數據庫:這一類數據庫主要會使用到一個哈希表,這個表中有一個特定的鍵和一個指針指向特定的數據;
- 列存儲數據庫:這部分數據庫通常是用來應對分佈式存儲的海量數據。鍵仍然存在,但是它們的特點是指向了多個列;
- 文檔型數據庫:同第一種鍵值存儲相類似。該類型的數據模型是版本化的文檔,半結構化的文檔以特定的格式存儲;
- 圖形(Graph)數據庫:使用圖模型存儲。

常見 NoSQL 數據庫:

- MongoDB:文檔型數據庫;功能豐富;查詢語言強大;併發效率不高,查詢效率不算高;
- Redis:field-value 存儲系統(主要面對內存數據庫,也可持久化);安全性;主從複製;運行異常快,支持事務,豐富類型的 field 類型。

關係型數據庫 VS 非關係型數據庫

非關係型數據庫的優勢:

  - 無需 SQL 的解析,所以性能非常高。有可以做的純內存操作,比如 Redis,單節點每秒可以處理超過 10 萬次讀寫操作。
  - NoSQL 數據庫是動態結構,可以很容易適應數據類型和結構的變化。
  - 容易集羣。

關係型數據庫的優勢:

  - 複雜查詢,可以用 SQL 語句方便的在多個表之間做非常複雜的數據查詢。
  - 事務支持,使得對於安全性能很高的數據訪問要求得以實現。

NoSQL 用於超大規模數據的存儲。(例如谷歌或 Facebook 每天爲他們的用戶收集萬億比特的數據)。這些類型的數據存儲不需要固定的模式,無需多餘操作就可以橫向擴展。

MongoDB 簡介

1)前景

隨着大數據的不斷髮展,非關係型數據庫已經變得越來越重要,相關的產品也都得到了飛速發展。

而其中 MongoDB 更是佼佼者,作爲高性能開源文檔數據庫,MongoDB 以敏捷、可擴展和對企業應用友好而著稱,因其操作簡單、完全免費、源碼公開等特點,受到了 IT 從業人員的青睞,並被廣泛部署於實際的生產環境中。

使用 MongoDB 的公司包括:BAT、360、Foursquare、Craiglist、迪士尼、SAP、Intuit、EA 等。

2)定義

MongoDB 是一個基於分佈式文件存儲的數據庫。由 C++ 語言編寫。旨在爲 WEB 應用提供可擴展的高性能數據存儲解決方案。

MongoDB 是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。

它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。

MongoDB 最大的特點是它支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。

3)數據模型

4)優點

MongoDB 的特點是高性能、易部署、易使用,存儲數據非常方便。

主要功能特性有:

- 面向集合存儲,易存儲對象類型的數據。
- 模式自由。
- 支持動態查詢。
- 支持完全索引,包含內部對象。
- 支持查詢。
- 支持複製和故障恢復。
- 使用高效的二進制數據存儲,包括大型對象(如視頻等)。
- 自動處理碎片,以支持雲計算層次的擴展性
- 支持 RUBY,PYTHON,JAVA,C++,PHP, JavaScript 等多種語言。
- 文件存儲格式爲 BSON(一種 JSON 的擴展)

5)BSON

BSON 是一種類似 JSON 的二進制形式的存儲格式,簡稱 Binary JSON,它和 JSON 一樣,支持內嵌的文檔對象和數組對象,但是 BSON 有 JSON 沒有的一些數據類型,如 Date 和 BinData 類型。

後面存在 MongoDB 數據庫裏面的全部都是 BSON 格式的數據。

MongoDB 安裝

MongoDB官網下載地址

1)安裝流程

安裝成功之後,會自動註冊一個 MongoDB 服務(Windows 中可以通過運行 services.msc),此服務開機自動啓動(也可以配置手動啓動)。

注意:要使用 MongoDB,此服務需運行中。

2)配置環境變量

配置環境變量可在任意位置使用 MongoDB 的命令。

找到系統屬性,高級系統設置,環境變量,配置舉例:

path=...;E:\dev\MongoDB\Server\4.0\bin

3)測試

打開命令行:輸入 mongo,若出來如下內容,證明安裝成功。

MongoDB 使用

對 MongoDB 數據庫操作需要其提供的內置命令來操作的。

1)基本命令

- show dbs:查看有數據的庫;
- use  庫名:若沒有則創建庫並切換,若有隻切換庫;
- db:顯示當前操作的庫;
- db.runCommand({"dropDatabase": 1}):刪除當前數據庫,注意此處的 1 沒加雙引號。

2)集合操作

- show collections                                      :顯示庫中的集合;
- db.createCollection("集合名字")                        : 創建集合;
- db.集合名.drop() 或 db.runCommand({"drop":"集合名"})    :刪除集合。

3)文檔操作

增加文檔

給某集合裏面增加文檔,注意:

- 若集合不存在,會自動創建集合;
- 保存成功之後,系統會自動給文檔增加一個 _id 主鍵字段,主鍵是每個文檔的唯一標識,其值不能重複,就像身份證是每個人編號是唯一的。

語法格式如下:

- db.集合名.insert(BSON 格式數據),若新增的文檔主鍵已經存在,insert 會不做操作並提示錯誤;
- db.集合名.save(BSON 格式數據),若新增的文檔主鍵已經存在,save 則更改原來的內容爲新內容。

db.students.insert({"name":"xx","age":18})

db.students.insert({"_id":ObjectId("5c457f78034a8e64b22cd683"),"name":"xx","age":19}) // 報錯 duplicate field error collection
db.students.save({"_id":ObjectId("5c457f78034a8e64b22cd683"),"name":"xx","age":19})  // 修改

查詢文檔

查詢集合中的文檔,語法格式如下:

- db.集合名.find()            :查詢集合中所有文檔;
- db.集合名.find().pretty()   :格式化查詢到的文檔;
- db.集合名.findOne()         :查詢集合中的第一個文檔,即插入最早那個。

db.students.find()
db.students.find().pretty()           
db.students.findOne()

修改文檔

修改集合中的文檔,語法格式如下:

- db.集合名.update(BSON 格式數據):注意:第一個參數查詢的條件,第二個參數是修改的內容,但主鍵是不能修改。

db.students.update({"name":"xx"}, {"age":88})                       // 注意原來的數據只剩下 {"age":88}
db.students.update({"name":"xx"}, {$set:{"age":88}})                // 這裏就只改原來文檔的 age 的值。  
db.students.update({"name":"xx"}, {$set:{"age":88}}, {multi:true})  // 默認只改先找的一條,若想改多條得設置 multi 參數爲 true

刪除文檔

刪除集合中的文旦,語法格式如下:

- db.集合名.remove()  :刪除集合中的文檔,可以指定條件。

db.集合名.remove({})                // 刪除集合中所有的文檔
db.集合名.remove({"name":"yy"})     // 刪除指定條件 name="yy" 的文檔

高級查詢

1)查詢 field = value 的文檔語法:db.集合名.find({ "field" : value })

// 查詢女歌星,即查詢 sex = "女"的歌星
db.singers.find({"sex":"女"})

2)查詢 field > value 的文檔語法:db.集合名.find({ "field" : { $gt: value } })

// 查詢年齡大於 53 的歌星
db.singers.find({"age": { $gt: 53 }})

3)查詢 field < value 的文檔語法:db.集合名.find({ "field" : { $lt: value } })

// 查詢年齡小於 35 歲的歌星
db.singers.find({"age": { $lt: 35 }})

4)查詢 field >= value 的文檔語法:db.集合名.find({ "field" : { $gte: value } })

// 查詢成績大於等於 95 的歌星
db.singers.find({"score": { $gte: 95 }})

5)查詢 field <= value 的文檔語法:db.集合名.find({ "field" : { $lte: value } })

// 查詢年齡在小於等於 32 歲的歌星。 
db.singers.find({"age": { $lte: 32 }})

6)查詢 min < field < max 的文檔語法:db.集合名.find({ "field" : { $gt: min , $lt: max } })

// 查詢年齡在 (30, 40) 歲之間的歌星
db.singers.find({"age": { $gt: 30 , $lt: 40 }})

7)查詢 field <> value 的文檔語法:db.集合名.find({ "field" : { $ne: value } })

// 查詢外國歌手
db.singers.find({"country": { $ne: "中國" }})

8)查詢 field % divisor == remainder 的文檔語法:db.集合名.find({ "field" : { $mod : [ divisor, remainder ] } })

// 查詢成績爲 5,15,25...95 的歌星。
db.singers.find({"score" : { $mod : [10, 5] }})

9)查詢 field = value1 OR field = value2 ... OR field = valueN OR 的文檔語法:db.集合名.{ field: { $in: [value1, value2, ... valueN ] } }

// 查詢序號(num)爲 3 或者 6 或者 9 的歌星
db.singers.find({ "num" : { $in: ["3", "6", "9"] } })

10)查詢 field <> value1 AND field <> value2 ... AND field <> valueN 的文檔語法:db.集合名.{ field: { $nin: [value1, value2, ... valueN ] } }

// 查詢國籍不爲美國和韓國的歌手
db.singers.find({"country" : { $nin: ["美國", "韓國"] }})

11)查詢文檔字段數量的語法:db.集合名.find({ "field" : { $size: num } }),注意 field 的值是數組。

// 查詢有 3 個代表作品的歌手
db.singers.find({"works" : { $size: 3 }})

12)查詢存在或不存在某個字段的的文檔語法:db.集合名.find({ "field" : { $exists : true|false } })

// 查詢包含 name 字段的歌手
db.singers.find({"name" : { $exists : true }})

13)查詢多個條件是或的關係的文檔語法:db.集合名.find({ $or : [expression1, expression2, ..., expressionN] })

// 查詢名詞是劉德華的歌手或者是女歌手
db.singers.find({$or : [{"name":"劉德華"}, {"sex":"女"}]})

14)查詢多個條件是且的關係的文檔語法:db.集合名.find({ $and : [expression1, expression2, ..., expressionN] })

// 查詢名字是劉德華且是女的歌手
db.singers.find({$and : [{"name":"劉德華"}, {"sex":"女"}]})

15)若字段的值是對象:db.集合名.find({ "字段名.對象屬性名":對象屬性值 })

db.students.insert({"name":"zs", "score":{"yw":80, "sx":91}})
db.students.insert({"name":"ls", "score":{"yw":77, "sx":95}})
// 查詢語文成績爲 80 的同學
db.students.find({"score.yw": 80})

16)排序查詢文檔,語法格式:db.集合名.find().sort({ "field" : -1 | 1}),注意 1 代表升序,-1 代表降序

// 對所有歌星安年齡排序
db.singers.find().sort({"age": 1})

17)限制查詢的個數,語法格式:db.集合名.find().limit(n)

// 實現輸出 5 條
db.singers.find().limit(5)

18)跳過多少條再查詢,語法格式:db.集合名.find().skip(n)

// 跳過 5 條查詢
db.list.find().skip(5)

19)分頁查詢:語法格式:db.集合名.find().skip(n).limit(n)

// 假如 101 條數據,每頁顯示 10 條,一共分 11 頁,那麼要查詢第 2 頁的文檔
// var pageSize = 10;
// var start = (2 - 1) * pageSize;
db.list.find().skip(start).limit(pagesize)

索引

索引支持MongoDB中查詢的高效執行。如果沒有索引,MongoDB必須執行集合掃描,即掃描集合中的每個文檔,以選擇與查詢語句匹配的文檔。如果查詢存在適當的索引,MongoDB可以使用索引來限制它必須檢查的文檔數。即可以使查詢更高效。

具體可以查看MongoDB中文社區:http://www.mongoing.com/archives/26867

另外,可以查看索引的應用例子:MongoDB地理索引

權限

讓數據安全, 避免數據泄露和丟失。

1)添加超級管理員用戶

use admin
db.createUser({"user":"用戶名", pwd:"密碼","roles"["root"]})

2)修改配置文件開啓認證

修改 MongoDB 根目錄下的 mongod.cfg 文件

security:
      authorization: enabled

3)重啓數據庫之後使用戶名和密碼連接數據庫

mongo -u 用戶名 -p 密碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章