哈囉,我們又見面了,今天先跟大家預告,接下來兩天假日不會有文章,因為我睡囉,因為我發現與其要提心吊膽的擔心進度,不如就放心好好休息,休息完再繼續戰鬥,但休息不是說完全耍廢,就是想到什麼還是做什麼,只是不寫文章,好吧,我覺得說再多,都不會有人相信我在假日還會做事 XD
名言截自 賭俠 | 周星馳
所以今天要做什麼呢 !? 我們來延續昨天的資料庫話題,昨天 Day14 瞭解了 MySQL
與 Django
的基本互動,感受到了關聯式資料庫的增查改刪,今天來感受一下 NoSQL 中熱門的 MongoDB,
詳細可以參考 (2018)[筆記] RDBMS v.s. NoSQL | 邁向王者的旅途,裡面有提到很重要的一點,就是關聯式的資料庫,要變更資料欄位,是一件很麻煩的事情,到底多麻煩呢?
假設原本有十萬筆文章的資料都是只有 標題
和 摘要
兩個欄位,那今天我想要新增一個 網址
的欄位,而且我希望這個 網址
欄位不能空白,這代表著十萬筆資料,都必須要每一筆都要有 網址
的資料存在,如果有一筆沒新增到 網址
就會報錯,這只是 "十萬筆資料" 且 "新增一個欄位的工作量",正常運作一段時間的伺服器資料庫,數量級別會是更龐大且複雜的。
簡單來講,關聯式 的好處是資料規格嚴謹、出錯率低,但缺點就是要擴大很麻煩,在現在這個資訊量爆炸且變化速度很快的時代,關聯式的缺點就被凸顯出來,所以出現 非關聯式 來解決這個問題,具備了彈性、可分散式儲存的優點,其餘講 非關聯式 好話的可以參考 NoSQL vs SQL Databases | MongoDB,由 MongoDB 官方來說服你使用 NoSQL
。
就算是 NoSQL
佔盡了各種好處,現在台灣很多企業依舊使用 Relational
,一方面是從舊換新的變動太麻煩了,一方面是近十年內的資訊發展,才慢慢凸顯出 NoSQL
的優點,還有現在學校培育出來的人才,還是學習關聯式的資料儲存方式,所以就算要找人來把資料庫改版,也不好找,所以就這兩種資料儲存方式都還是需要學習的。
MongoDB
在 MongoDB 首頁 比較難找到下載點,在 Software 內的 Community Server 裡,如果點選官網首頁的 Start free 按鈕,是要註冊申請 MongoDB Atlas Cloud Database
的,不要點錯囉。
安裝好之後,就會自動啟動 MongoDB Compass
,也就是類似 MySQL Workbench
的圖形化介面工具,但這兩個看起來就是不同年代的產品 XD。
MongoDB compass
相當於 MySQL Workbench
,是資料庫的圖形化介面 (GUI),介面十分簡潔、跟 MySQL Workbench
完全不能比 XD,這才是現代的產品該有的樣子阿 !
MongoDB
的指令前需要做什麼 ?雖然 MongoDB 的 GUI 好用,可是想要更瞭解 MongoDB 的話,指令還是少不了的,可是,安裝完 MongoDB 之後,不會自動幫你把指令的路徑加到環境變數裡,所以你必須自己來。
預設路徑是放在 C:\Program Files\MongoDB\Server\4.2\bin
,所以就打開系統環境變數,新增進去到 Path 裡,Win10 新增環境變數的方法可以參考 (2019) 設定環境變數讓 Windows cmd 命令列可以執行 php 指令。
Windows cmd 必須重開,才能吃到變更後的環境變數,可以輸入 $ mongo
,來檢查是否有變更到環境變數,這是要進到 MongoDB Shell 的指令。
在你安裝完之後,預設就會幫你啟動背景服務,在 Windows 可以用 $ tasklist | findstr mongo
來檢查,這是 windows 的指令,如果你是 Linux/Mac 用戶,可以使用 $ ps -aux | grep mongo
。
mongod.exe 10636 Services 0 31,960 K
如果有出現 mongod
的 process,就代表現在 MongoDB Deamon 是運行的狀態。
輸入 $ mongod
來啟動 MongoDB 的 Deamon 服務,mongod
的 d 也就是代表 deamon 的意思。
2020-02-21T14:55:49.894+0800 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
2020-02-21T14:55:50.235+0800 I CONTROL [initandlisten] MongoDB starting : pid=5388 port=27017 dbpath=C:\data\db\ 64-bit host=DESKTOP-014F2HS
2020-02-21T14:55:50.235+0800 I CONTROL [initandlisten] targetMinOS: Windows 7/Windows Server 2008 R2
2020-02-21T14:55:50.237+0800 I CONTROL [initandlisten] db version v4.2.3
2020-02-21T14:55:50.242+0800 I CONTROL [initandlisten] git version: 6874650b362138df74be53d366bbefc321ea32d4
2020-02-21T14:55:50.243+0800 I CONTROL [initandlisten] allocator: tcmalloc
2020-02-21T14:55:50.244+0800 I CONTROL [initandlisten] modules: none
2020-02-21T14:55:50.244+0800 I CONTROL [initandlisten] build environment:
2020-02-21T14:55:50.249+0800 I CONTROL [initandlisten] distmod: 2012plus
2020-02-21T14:55:50.249+0800 I CONTROL [initandlisten] distarch: x86_64
2020-02-21T14:55:50.255+0800 I CONTROL [initandlisten] target_arch: x86_64
2020-02-21T14:55:50.255+0800 I CONTROL [initandlisten] options: {}
2020-02-21T14:55:50.258+0800 I STORAGE [initandlisten] exception in initAndListen: NonExistentPath: Data directory C:\data\db\ not found., terminating
2020-02-21T14:55:50.258+0800 I NETWORK [initandlisten] shutdown: going to close listening sockets...
2020-02-21T14:55:50.259+0800 I - [initandlisten] Stopping further Flow Control ticket acquisitions.
2020-02-21T14:55:50.267+0800 I CONTROL [initandlisten] now exiting
2020-02-21T14:55:50.269+0800 I CONTROL [initandlisten] shutting down with code:100
從這邊可以看到預設是開在 27017
的 port,db 路徑在 C:\data\db\
,然後我這邊是開 失敗 了! 為什麼呢 !?
仔細看錯誤訊息是丟出了 NonExistentPath
的 Exception,因為雖然 MongoDB 的預設路徑是在 C:\data\db\
,可是它不會幫你創好這兩個資料夾,所以你需要到 C 槽自己創一個名為 data 的資料夾,然後進去 data
資料夾之後,再創一個 db
資料夾;你也可以用 $ mongod --dbpath yourpath
來指定你的 database 資料要放在哪裡。
安裝完 MongoDB 後,它是預設會在你每次重開機都會自動重啟的,但每個人的安裝過程中,有可能不太一樣,所以需要學會怎麼查看 Deamon 的啟動狀況。
從 工作管理員 的 服務 分頁,找到 MongoDB 的服務,右鍵→ 開啟服務
進到 服務
的視窗,找到 MongoDB Server,如果 啟動類型
是自動,就代表每次重開機都會自動重啟。
再輸入 $ mongo
來進入到 MongoDB Shell
MongoDB shell version v4.2.3
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("df28bf2a-a3e1-4e26-ab78-dde227e69371") }
MongoDB server version: 4.2.3
Server has startup warnings:
2020-02-21T11:13:58.695+0800 I CONTROL [initandlisten]
2020-02-21T11:13:58.695+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-02-21T11:13:58.695+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2020-02-21T11:13:58.695+0800 I CONTROL [initandlisten]
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
>
可以看出預設連到的 mongoDB 是開在 127.0.0.1
的 27017
port。
補充:
想知道某個 windows cmd 的指令的話,可以這樣下 google 關鍵字,xxx cmd in windows
,舉例來說,我這次找 ps 指令是用ps cmd in windows
才找到的、找 grep 也是一樣的道理。
然後想知道指令的 options 可以帶入哪些參數,可以在 windows cmd 這樣查$ help xxx
,像我這次查 tasklist 就用$ help tasklist
。
127.0.0.1
的 27017
port (預設)在這邊一次整理出來,比較不會忘 XD
啟動 MongoDB Deamon (前景運作,active mode)
$ mongod
也就是可以在終端機看到所有的 log 資訊
啟動 MongoDB Deamon (背景運作,Linux)
$ mongod --fork --logpath /var/log/mongodb/mongod.log
啟動 MongoDB Deamon (背景運作,Windows)
$ net start MongoDB
雖然會出現錯誤,可是 Deamon 還是會啟動
系統發生 5 錯誤。
存取被拒。
關閉 MongoDB Deamon (Linux)
$ mongod --shutdown
關閉 MongoDB Deamon (Windows)
$ mongo
→ 進到 MongoDB Shell
mongo> user admin
→ 進到 admin 的 database
mongo> db.shutdownService()
關於 Windows 的啟動、關閉指令,可以參考 官方文件
關於 Linux 的啟動、關閉指令,可以參考 官方文件
輸入 mongo> help
就有許多關於 MongoDB Shell 指令的說明。
我們要新增一個叫做 django
的 database,等等我們要用在 django 的 settings.py
檔案中。
mongo> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
mongo> use django
switched to db django
mongo> db
django
如果你對 MySQL
還有點感覺的話,你會覺得奇怪,為什麼還沒有 create 資料庫,就可以 use 資料庫,這一開始也很困擾我,因為我找了半天,一直找不到 create 的指令 ! 但實際上是,可以直接用 use
來新增一個資料庫,但,在你新增一筆資料進去資料庫之前,它是不會顯示出來的
所以當我再一次執行 mongo> show dbs
,還是一樣長這樣
admin 0.000GB
config 0.000GB
local 0.000GB
那就新增一筆資料到 django
collections 裡
mongo> db.django.insert({"first": "data"})
這個 db
代表的是名為 django
database,而 db.django
的 django 代表的是 名為 django
的 collections
查看現在 django collections 裡面的資料
mongo> db.django.find()
{ "_id" : ObjectId("5e4f8eeb59c15ec661e9362c"), "first" : "data" }
以上的指令流程在 MongoDB Compass 是非常簡單的點點點的動作,如果你看暈頭了,就直接上 Compass 操作一次,就可以感受到它的介面設計得多棒了 XD
因為目前 Django
3.0.3 版,還沒有官方支援 MongoDB
,所以需要透過第三方套件 Djongo
來做到(我沒有拼錯哦)。
希望達到的目標就是透過 Django
來操作 MongoDB
的資料,只要走過前面的建置過程,對於 django 的使用者來說,寫的 python code 都是一樣的,只要專注在 models.py
與 views.py
的程式邏輯就好了,剩下的資料庫操作細節,只要交給 django 和 engine 即可。
djongo
套件,才能在 django 使用 MongoDB記得先進去你的 virtul environment
$ yourvirenv\Scripts\activate
(Windows)
$ source yourvirenv/bin/activate
(Linux)
安裝 djongo
(django-env) $ pip install djongo
settings.py
'default': {
'ENGINE': 'djongo',
# 這個 NAME 必須跟我們在 MongoDB
# 所創建的 database 名字一模一樣
'NAME': 'django',
# HOST 的這串,到 Compass 去複製
'HOST': 'mongodb://127.0.0.1:27017/?readPreference=primary&appname=MongoDB%20Compass%20Community&ssl=false',
},
settings.py
的 HOST 欄位先打開 MongoDB Compass,點 Fill in connection fields individually
按鈕
填入 Hostname 和 Port,再按下 Paste connection string
把這段複製起來,貼到 settings.py
的 HOST 中
models.py
的欄位對應到 MongoDB$ python manage.py makemigrations shop
$ python manage.py migrate
到 Compass 就可以看到在 django
database 底下,除了原本的 django
collections,還多了很多個 collections 呢 ~
到這邊,你的 MongoDB
和 Django
就已經連動起來了 !
Django
在 MongoDB
的 增讀更刪(CRUD
)在 django 端,只要連動成功了任何一種 DB,不論是 Relational
或 NoSQL
,那麼新增、讀取、更新、刪除的 python 程式碼,都是不變的,這就是框架(Framework)替我們做的事。
Create
) 透過 Django 在 MongoDB 新增資料其中相關的 code,可以參考 Day14,這邊只貼 views.py
的 code
views.py
def insert_view(request):
for i in range(5):
product = Product()
product.name = "測試" + str(random.randint(0, 5))
product.price = random.randint(1, 500)
product.save()
return HttpResponse("批次新增資料完成")
127.0.0.1:8000/insert/
Read
) 透過 Django 在 MongoDB 讀取資料views.py
def lookup_view(request):
result = Product.objects.all()
mlist = []
for item in result:
content = {"product name": item.name, "price": float(item.price)}
mlist.append(content)
return HttpResponse(mlist)
127.0.0.1:8000/lookup/
會出錯,那是因為 MongoDB 在你創建 collection 的時候,會自動幫你加一筆空的 object 在裡面,把它刪掉,就可以了。這個 bug,卡了我一個多小時 ...
Update
) 透過 Django 在 MongoDB 更新資料views.py
def modify_view(request):
product = Product.objects.get(id=1)
product.name = "我是後來才修改的產品"
product.save()
return HttpResponse('修改完成,到 Mongo Compass 確認資料')
127.0.0.1:8000/modify
對 id=1 的資料更改成功 ~
Delete
) 透過 Django 在 MongoDB 刪除資料views.py
def delect_view(request):
product = Product.objects.get(id=1)
product.delete()
return HttpResponse('刪除 id=1 的資料成功,請到 SQL shell 下指令\nsql> select * from product')
127.0.0.1:8000/delete
id=1 被刪除了 ~
真糟糕,我忘記改 code 就先訪問這個網址,為了保持截圖的資料一致,所以我就不改 MySQL 那串指示文字了,拍謝造成大家混亂 QQ
這兩天連續地體驗了兩種不同的資料庫,從這兩天的 code 來看可以發現,對於 Django
開發邏輯層面,是完全不受影響的,這一點真的要給 Django
拍拍手,對於開發人員來講,是一件很重要的事情,不用去處理到非常細節的資料庫操作。
但有些坑還是得親自踩過才知道 QQ,例如 MongoDB
不像 MySQL
一樣有 AUTO INCREMENT
的概念,相對應的,在 MongoDB
裡,每筆資料都會有自己的 object id,像這樣的差異,在切換不同的資料庫時,就容易出現問題,是開發者必須要自己注意的。
提醒各位,明後兩天 RS 有事要先休息一下,所以 Android開發者的30天後端養成故事
停刊兩天。
我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。
大大您好,請教一下關於使用NOSQL~
是否我在Django進行model的建立、欄位的新增就可以不透過migrate了?