# MongoDB 學習筆記 ![image](https://hackmd.io/_uploads/HJq1ncDyC.png) ## 前言 因為工作上遇到某個專案資料儲存相關的問題,我們專案需求使用 PostgreSQL,但這個資料特性是欄位長度不固定,因此起初的做法是將每一筆資料切片成多段(以欄位、值的方式切分)存進資料庫,來解決長度不一的問題;但實作後發現效率實在太差,才開始考慮使用 NoSQL 的資料庫比較一下差異。 * [安裝 MongoDB](#安裝-MongoDB) * [安裝 MongoDB for Ubuntu 22.04](https://hackmd.io/@e9gZC-1CQNOzcD2pMY6apA/BybNPRlxA) * [安裝管理工具](#安裝管理工具) * [資料庫基本操作(CRUD)](#資料庫基本操作(CRUD)) ## 安裝 MongoDB > ### MongoDB 產品簡介 > MongoDB 是一個物件導向的 NoSQL 資料庫,他們家有兩個主要產品線: > * **MongoDB Atlas** > * **MongoDB Server**。 > > MongoDB Atlas 提供雲端資料庫平台服務(按需付費),而 MongoDB Server 提供使用者下載至本地端自行部署的服務,其中又分為 Community Server 和 Enterprise Server 兩種版本,這次我們選擇使用 Community Server 免費開源的版本。 > > 若對於雲端部署有興趣的可以參考這篇文章 [MongoDB Atlas 教學](https://mengchiehliu.github.io/posts/pymongo/) 1. 到 [MongoDB 官網的 Community Server](https://www.mongodb.com/try/download/community) 找到最新版本下載 ![image](https://hackmd.io/_uploads/rJnBD-u10.png) 2. 將下載檔案解壓縮後,拖曳至專案目錄下,並將資料夾名稱改名為`mongodb`,方便後續操作它 ![image](https://hackmd.io/_uploads/B17OvZOJC.png) 3. 在專案目錄下建立`mongodb-data`資料夾,用來存放資料 ![image](https://hackmd.io/_uploads/rJRcPZuJ0.png) 4. 輸入指令開啟資料庫`mongodb/bin/mongod --dbpath ./mongodb-data` 初次開啟時會跳出此警告,接著我們去系統設定調整一下 ![image](https://hackmd.io/_uploads/B1xOjvbu1A.png) 5. 打開隱私權與安全性,找到被阻擋的訊息,點選強制允許即可 ![image](https://hackmd.io/_uploads/BJynDWuyR.png) 6. 出現`Waiting for connections port 27017`,表示資料庫服務已啟用 ![image](https://hackmd.io/_uploads/BJVnvbuJA.png) ## 安裝管理工具 資料庫啟用之後,我們需要安裝管理工具來連線操作資料庫,官網提供兩種選項,擇一安裝即可 1. **[MongoDB Shell (CLI)](https://www.mongodb.com/try/download/shell)** ![image](https://hackmd.io/_uploads/Hy5JwiDyR.png) 2. **[MongoDB Compass (GUI)](https://www.mongodb.com/try/download/compass)** ![image](https://hackmd.io/_uploads/rkHk_jPJC.png) > 上述兩種工具安裝後直接執行即可,需注意的是要確認資料庫服務已開啟 ## 資料庫基本操作(CRUD) 首先我們要先了解在 MongoDB 資料庫裡最基本的**組成概念**、**資料型別** **組成概念** Database 包含了多個 Collections,而 Collection 由多個 Documents 所組成。 ![image](https://hackmd.io/_uploads/H1RMwRPyA.png) >這張圖以 SQL vs MongoDB 來比較兩者的對應關係。 ![image](https://hackmd.io/_uploads/S1cgOCw1C.png) **資料型別** MongoDB 所儲存的格式是Binary JSON 通稱為 BSON,都是以 JSON 的格式呈現,但儲存的資料型別還是有差異的,以下列表取自[ MongoDB Docs](https://www.mongodb.com/docs/manual/reference/bson-types/) ,點進去可以看到詳細說明。 | Type | Number | Alias | Notes | |--------------------|--------|------------|-----------------| | Double | 1 | "double" | | | String | 2 | "string" | | | Object | 3 | "object" | | | Array | 4 | "array" | | | Binary data | 5 | "binData" | | | Undefined | 6 | "undefined"| Deprecated. | | ObjectId | 7 | "objectId" | | | Boolean | 8 | "bool" | | | Date | 9 | "date" | | | Null | 10 | "null" | | | Regular Expression | 11 | "regex" | | | DBPointer | 12 | "dbPointer"| Deprecated. | | JavaScript | 13 | "javascript"| | | Symbol | 14 | "symbol" | Deprecated. | | 32-bit integer | 16 | "int" | | | Timestamp | 17 | "timestamp"| | | 64-bit integer | 18 | "long" | | | Decimal128 | 19 | "decimal" | | | Min key | -1 | "minKey" | | | Max key | 127 | "maxKey" | | ### 基本指令 * 列出所有 database `show dbs` * 切換至指定的 database (若不存在則創建新的 database) `use <database>` * 建立 collection `db.createCollection("rawdata")` * 列出當前 database 所有的 collection `db.getCollectionNames()` * 顯示當前的 database `db.getName()` * 刪除當前的 database `db.fropDatabase()` * 刪除指定的 collection `db.` ### 新增指令 * 新增單筆資料 ![image](https://hackmd.io/_uploads/Hkq5VnvkR.png) ```mongodb= # 新增單筆資料 # db.rawdata.insertOne(document, options) db.rawdata.insertOne({ "identity/LineItemId": "q4rf7k5pgrrbbudrcjzpkdfhwpprovpgwklgdnw7xy5shpny25ha", "identity/TimeInterval": "2024-01-01T00:00:00Z/2024-02-01T00:00:00Z", "lineItem/UsageAccountId": "934075583300", }) # 新增成功的話會回傳以下資訊 { acknowledged: true, insertedId: ObjectId('660a346f81e20dbb5ca2948f') } ``` * 新增多筆資料 ![image](https://hackmd.io/_uploads/Hkfc8hwJ0.png) ```mongodb= # 新增多筆資料 # db.rawdata.insertMany(documents, options) db.rawdata.insertMany([ { "name": "wilson", "age": 28, }, { "name": "tony", "age": 46, }, ]) # 新增成功的話回傳以下資訊 { acknowledged: true, insertedIds: { '0': ObjectId('660a365681e20dbb5ca29490'), '1': ObjectId('660a365681e20dbb5ca29491') } } ``` ### 查詢指令 * 查詢單筆資料 ```mongodb= # 查詢單筆資料 db.rawdata.findOne({"name": "wilson"}) # 查詢成功的話回傳第一筆符合項目,否則回傳 null ``` ![image](https://hackmd.io/_uploads/SyMdp6P1R.png) * 查詢多筆資料 ```mongodb= # 查詢多筆資料 db.rawdata.find({"name": "wilson"}) # 查詢成功的話會回傳所有符合的項目,否則回傳 null ``` ![image](https://hackmd.io/_uploads/SkkzFk_1C.png) ### 進階查詢指令 這邊整理了一些常用的進階查詢 Query 範例,參考自[ MongoDB 官方文檔](https://www.mongodb.com/docs/manual/reference/operator/query-comparison/),介紹各類型運算子的定義及用法,有興趣的朋友可以點進去閱讀一下 | Name | Description | Note | | ---- | ------------------------------------------------------------------- | --- | | $eq | Matches values that are equal to a specified value. | 等於 | | $gt | Matches values that are greater than a specified value. | 大於 | | $gte | Matches values that are greater than or equal to a specified value. | 大於等於 | | $in | Matches any of the values specified in an array. |符合其中一個 | | $lt | Matches values that are less than a specified value. |小於 | | $lte | Matches values that are less than or equal to a specified value. | 小於等於 | | $ne | Matches all values that are not equal to a specified value. |不等於 | | $nin | Matches none of the values specified in an array. |不符合其中一個 | * 查詢 name 符合 "wil" 字段的所有項目(正則表達式) `db.rawdata.find({name: { $regex: /wil/}})` ![image](https://hackmd.io/_uploads/r1B6EldkC.png) * 查詢 age 小於 30 的所有項目 `db.rawdata.find({age: { $lt: 30}})` ![image](https://hackmd.io/_uploads/BJS6Beu1R.png) * 查詢 age 小於 30 的所有項目總數 `db.rawdata.find({age: { $lt: 30}}).count()` ![image](https://hackmd.io/_uploads/Hye2ebOkR.png) > **Tips** > `$eq`, `$in`這兩個蠻容易搞混,這邊我是這樣理解,他倆比較像是“且”跟“或”的關係 > > 1. 這邊使用`$eq`篩選 name 符合 wilson 且符合 tony 的documents,故沒有回傳符合的結果 > ![image](https://hackmd.io/_uploads/H1UDHgYJ0.png) > > 2. 而這邊使用`$in`篩選 name 符合 wilson 或符合 tony 的 documents,因此回傳了兩筆結果 > ![image](https://hackmd.io/_uploads/BJCVBgtyR.png) ### 修改指令 TODO ### 刪除指令 同樣也能運用上述的運算子來增加條件 * 刪除單筆資料(將 age 是 28 的刪除) `db.rawdata.deleteOne({age: "28"})` ![image](https://hackmd.io/_uploads/BJPEGWuyC.png) * 刪除多筆資料(正則表達式,將 name 是 m 開頭的刪除) `db.rawdata.deleteMany({name: { $regex: /^m/}})` ![image](https://hackmd.io/_uploads/HJDBBWOy0.png) ## 參考文章 [Mongodb 教學:從安裝到啟動基本操作教學](https://tw.alphacamp.co/blog/mongodb-intro) [從入門到精通 MongoDB 鐵人賽](https://ithelp.ithome.com.tw/users/20130448/ironman/3618)