iT邦幫忙

0

[不做怎麼知道系列之Android開發者的30天後端養成故事 Day15] - 後端核心中的新星 #資料庫 #MongoDB #NoSQL

Sam 2020-02-22 00:17:442127 瀏覽

https://ithelp.ithome.com.tw/upload/images/20200221/20124548yaCPb84695.png

哈囉,我們又見面了,今天先跟大家預告,接下來兩天假日不會有文章,因為我睡囉,因為我發現與其要提心吊膽的擔心進度,不如就放心好好休息,休息完再繼續戰鬥,但休息不是說完全耍廢,就是想到什麼還是做什麼,只是不寫文章,好吧,我覺得說再多,都不會有人相信我在假日還會做事 XD

https://ithelp.ithome.com.tw/upload/images/20200221/201245481WTc6DJdCT.png

名言截自 賭俠 | 周星馳

所以今天要做什麼呢 !? 我們來延續昨天的資料庫話題,昨天 Day14 瞭解了 MySQLDjango 的基本互動,感受到了關聯式資料庫的增查改刪,今天來感受一下 NoSQL 中熱門的 MongoDB

關聯式(Relational) vs. 非關聯式(NoSQL)

詳細可以參考 (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 的,不要點錯囉。

https://ithelp.ithome.com.tw/upload/images/20200221/201245483SnIFY5Qv4.png

安裝好之後,就會自動啟動 MongoDB Compass,也就是類似 MySQL Workbench 的圖形化介面工具,但這兩個看起來就是不同年代的產品 XD。

https://ithelp.ithome.com.tw/upload/images/20200221/20124548Gs9wOniCz3.png

MongoDB compass

相當於 MySQL Workbench,是資料庫的圖形化介面 (GUI),介面十分簡潔、跟 MySQL Workbench 完全不能比 XD,這才是現代的產品該有的樣子阿 !

https://ithelp.ithome.com.tw/upload/images/20200221/20124548vms9JuTN6e.png

使用 MongoDB 的指令前需要做什麼 ?

雖然 MongoDB 的 GUI 好用,可是想要更瞭解 MongoDB 的話,指令還是少不了的,可是,安裝完 MongoDB 之後,不會自動幫你把指令的路徑加到環境變數裡,所以你必須自己來。

新增 MongoDB 的指令路徑到環境變數

預設路徑是放在 C:\Program Files\MongoDB\Server\4.2\bin,所以就打開系統環境變數,新增進去到 Path 裡,Win10 新增環境變數的方法可以參考 (2019) 設定環境變數讓 Windows cmd 命令列可以執行 php 指令

https://ithelp.ithome.com.tw/upload/images/20200221/20124548EPEQrHYJVZ.png

檢查是否有加進環境變數

Windows cmd 必須重開,才能吃到變更後的環境變數,可以輸入 $ mongo,來檢查是否有變更到環境變數,這是要進到 MongoDB Shell 的指令。

啟動 MongoDB Deamon,也就是把 DB 服務開在背景執行

在你安裝完之後,預設就會幫你啟動背景服務,在 Windows 可以用 $ tasklist | findstr mongo 來檢查,這是 windows 的指令,如果你是 Linux/Mac 用戶,可以使用 $ ps -aux | grep mongo

mongod.exe                   10636 Services                   0     31,960 K

如果有出現 mongod 的 process,就代表現在 MongoDB Deamon 是運行的狀態。

如果不知道為什麼 MongoDB 被關掉了,該怎麼手動執行 MongoDB Daemon 呢?

輸入 $ 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\,然後我這邊是開 失敗 了! 為什麼呢 !?

MongoDB 啟動不了怎麼辦 !?

仔細看錯誤訊息是丟出了 NonExistentPath 的 Exception,因為雖然 MongoDB 的預設路徑是在 C:\data\db\,可是它不會幫你創好這兩個資料夾,所以你需要到 C 槽自己創一個名為 data 的資料夾,然後進去 data 資料夾之後,再創一個 db 資料夾;你也可以用 $ mongod --dbpath yourpath 來指定你的 database 資料要放在哪裡。

怎麼查看我的 MongoDB Deamon 啟動狀況 ?

安裝完 MongoDB 後,它是預設會在你每次重開機都會自動重啟的,但每個人的安裝過程中,有可能不太一樣,所以需要學會怎麼查看 Deamon 的啟動狀況。

工作管理員服務 分頁,找到 MongoDB 的服務,右鍵→ 開啟服務

https://ithelp.ithome.com.tw/upload/images/20200221/20124548rF8wOF3cFz.png

進到 服務 的視窗,找到 MongoDB Server,如果 啟動類型 是自動,就代表每次重開機都會自動重啟。

https://ithelp.ithome.com.tw/upload/images/20200221/20124548UN8nas7ThX.png

開始進入到 MongoDB Shell,感受指令

再輸入 $ 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.127017 port。

補充:
想知道某個 windows cmd 的指令的話,可以這樣下 google 關鍵字,xxx cmd in windows,舉例來說,我這次找 ps 指令是用 ps cmd in windows 才找到的、找 grep 也是一樣的道理。
然後想知道指令的 options 可以帶入哪些參數,可以在 windows cmd 這樣查 $ help xxx,像我這次查 tasklist 就用 $ help tasklist

也可以用 MongoDB Compass 連線 127.0.0.127017 port (預設)

https://ithelp.ithome.com.tw/upload/images/20200221/20124548O5cizkw8S7.png

常用的 MongoDB 指令有哪些呢 ?

在這邊一次整理出來,比較不會忘 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 的啟動、關閉指令,可以參考 官方文件

該怎麼知道有哪些 Shell 指令可以用 ?

輸入 mongo> help

https://ithelp.ithome.com.tw/upload/images/20200221/20124548oxVwqD4wt8.png

就有許多關於 MongoDB Shell 指令的說明。

以 MongoDB Shell 指令新增一個資料庫

我們要新增一個叫做 django 的 database,等等我們要用在 django 的 settings.py 檔案中。

確認目前 database 有哪些

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

MongoDB 與 Django 連動

因為目前 Django 3.0.3 版,還沒有官方支援 MongoDB,所以需要透過第三方套件 Djongo 來做到(我沒有拼錯哦)。

希望達到的目標就是透過 Django 來操作 MongoDB 的資料,只要走過前面的建置過程,對於 django 的使用者來說,寫的 python code 都是一樣的,只要專注在 models.pyviews.py 的程式邏輯就好了,剩下的資料庫操作細節,只要交給 django 和 engine 即可。

先安裝 djongo 套件,才能在 django 使用 MongoDB

  • 記得先進去你的 virtul environment

    $ yourvirenv\Scripts\activate (Windows)

    $ source yourvirenv/bin/activate (Linux)

  • 安裝 djongo

    (django-env) $ pip install djongo

開始連接 MongoDB

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',
},

到 Compass 複製 settings.py 的 HOST 欄位

先打開 MongoDB Compass,點 Fill in connection fields individually 按鈕

https://ithelp.ithome.com.tw/upload/images/20200221/20124548o8USDGFQFT.png

填入 Hostname 和 Port,再按下 Paste connection string

https://ithelp.ithome.com.tw/upload/images/20200221/20124548pJjPHsQWRu.png

把這段複製起來,貼到 settings.py 的 HOST 中

https://ithelp.ithome.com.tw/upload/images/20200221/201245486ZfBPouuCZ.png

把舊的 migrations 刪掉

https://ithelp.ithome.com.tw/upload/images/20200221/20124548ZgLMXVQj0V.png

重新將 models.py 的欄位對應到 MongoDB

$ python manage.py makemigrations shop

$ python manage.py migrate

到 Compass 就可以看到在 django database 底下,除了原本的 django collections,還多了很多個 collections 呢 ~

https://ithelp.ithome.com.tw/upload/images/20200221/20124548iS2yhLj5FA.png

到這邊,你的 MongoDBDjango 就已經連動起來了 !

DjangoMongoDB 的 增讀更刪(CRUD)

在 django 端,只要連動成功了任何一種 DB,不論是 RelationalNoSQL,那麼新增、讀取、更新、刪除的 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/

https://ithelp.ithome.com.tw/upload/images/20200221/20124548fnroS1u0KS.png

檢查是否新增成功

https://ithelp.ithome.com.tw/upload/images/20200221/20124548OhzYNlxM9B.png

(讀, 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/

https://ithelp.ithome.com.tw/upload/images/20200221/20124548Y8JRkX7MvO.png

會出錯,那是因為 MongoDB 在你創建 collection 的時候,會自動幫你加一筆空的 object 在裡面,把它刪掉,就可以了。這個 bug,卡了我一個多小時 ...

https://ithelp.ithome.com.tw/upload/images/20200222/20124548LgLsqSQXBq.png

https://ithelp.ithome.com.tw/upload/images/20200222/20124548ciXnjFdDoA.png

(更, 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

https://ithelp.ithome.com.tw/upload/images/20200222/20124548ID7E4Qbf5p.png

結果

對 id=1 的資料更改成功 ~

https://ithelp.ithome.com.tw/upload/images/20200222/20124548y0nsBYHJMa.png

(刪, 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

https://ithelp.ithome.com.tw/upload/images/20200222/201245483P1GmvGGoJ.png

結果

id=1 被刪除了 ~

https://ithelp.ithome.com.tw/upload/images/20200222/2012454895Otupzq65.png

真糟糕,我忘記改 code 就先訪問這個網址,為了保持截圖的資料一致,所以我就不改 MySQL 那串指示文字了,拍謝造成大家混亂 QQ

單日心得總結

這兩天連續地體驗了兩種不同的資料庫,從這兩天的 code 來看可以發現,對於 Django 開發邏輯層面,是完全不受影響的,這一點真的要給 Django 拍拍手,對於開發人員來講,是一件很重要的事情,不用去處理到非常細節的資料庫操作。

但有些坑還是得親自踩過才知道 QQ,例如 MongoDB 不像 MySQL 一樣有 AUTO INCREMENT 的概念,相對應的,在 MongoDB 裡,每筆資料都會有自己的 object id,像這樣的差異,在切換不同的資料庫時,就容易出現問題,是開發者必須要自己注意的。

提醒各位,明後兩天 RS 有事要先休息一下,所以 Android開發者的30天後端養成故事 停刊兩天。

我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。


https://ithelp.ithome.com.tw/upload/images/20200219/20124548meDsnCPamL.png


尚未有邦友留言

立即登入留言