專案開發難免要使用到 NoSQL,其中最具代表性也最常用的,無疑就是儲存資料結構和 JSON 十分貼近的 MongoDB。

目前工作專案中,存在著需要大量儲存 IoT gateway config 設定的需求,這些 config 記載著所有連接 gateway 的 sensor 設定狀態,是典型的多層結構,且不同 sensor 的 config,其層級、數量並不完全一致,而不同 gateway 之間的差異更大。

本來使用 MySQL 儲存,table 間的關係十分凌亂且複雜,ERD 都畫得很辛苦。

而這種資料特性,正是 MongoDB 擅長的舞台。

用 MongoEngine 整合 Django 與 MongoDB

由於專案以 Django 建構,所以 MongoDB 導入勢必要考慮到與 Django 的相容,而且必須是 ODM(文件型 NoSQL 的 ORM)框架,方便以物件形態操作資料,最好能和settings.py有一定的整合。

經過團隊一番研究與討論,還是決定採用 Python 最主流的 MongoDB ODM 框架——MongoEngine

本篇主要整理,Django 專案整合 MongoEngine 時,在設定上的一些重點。


前言:ODM vs ORM

ORM(Object–relational mapping)相信大家都已經相當熟悉,無須贅述。

而 ODM(Object-document mapping)則是「文件型(Document)」NoSQL 版的 ORM,由於 NoSQL 資料庫種類眾多,資料類型也各有不同。

所以 ODM 一詞,理論上只適用於文件型的 NoSQL 資料庫,在此即為 MongoDB。

不過,我覺得兩者的區分並不是特別重要,ORM 是通俗、常見的詞,而 ODM 主要是強調了「文件型 NoSQL」這個特性。

在我看來,把它們都粗略地統稱為 ORM,也未嘗不可。

MongoEngine 簡介

MongoEngine is a Python Object-Document Mapper for working with MongoDB.

Python ODM 中的 MongoEngine,就像 ORM 中的 SQLAlchemy,兩者在各自領域的代表性相近,且都不和任何 Web 框架綁定,可以單獨使用。

尤其使用像 Django、Flask 等 Web 框架時,特別需要!

ORM 之必要

若不將資料庫中儲存的資料先轉換為物件,把底層資料的細節先隱藏起來,對開發者在資料的操作與調度上較不友善,因為不必要的資訊太多。

且專案程式碼中,若存在著底層資料庫的直接查詢內容(比如 raw SQL 指令),整體也會相對難讀,也難維護。

所以 ORM 才會是 Django 或 Flask 等後端 Web 框架,在使用上的核心元素。而操作 MongoDB 時也需要類似的工具,而非直接透過 PyMongo 進行 pipeline 操作。

MongoEngine 是 Python 中最具代表性的 MongoDB ODM 框架,地位類似於 Node.js 中的 Mongoose

Django 專案設定 MongoEngine

前面提過,MongoEngine 並不和任何 Web 框架綁定,所以它自然不是為 Django 而生的產物。

如果用過 Flask 這種小型框架,通常立刻能聯想到:這種情況肯定會有整合型的外掛可供選擇,而且名字通常就是把兩個套件的名字結合在一起。

沒錯,這裡也是,即同樣由 MongoEngine 團隊開發的——django-mongoengine

Django-MongoEngine 主要功能

GitHub 頁面可知,django-mongoengine只是提供了一些簡單的 Django 整合,所以它並不是必要。

它甚至連獨立的文件網頁都沒有,實在有點無足輕重。

看起來大致有三個作用:

  1. MONGODB_DATABASES設定:下文會提及,這可能就是它最大的作用了。
  2. 重新封裝,增加了 Django 特色的 ODM 類別、欄位
  3. Session 整合設定

如果上述三者都不是必要需求,或許就不一定要安裝了。


安裝 Django-MongoEngine

1
pip install django-mongoengine

作為進一步封裝 MongoEngine 的整合性套件,安裝django-mongoengine自然也會同時安裝mongoengine

還是要再次提醒,不安裝它,一樣可以在 Django 中輕鬆使用 MongoEngine 的主要功能,只是裝了會更加方便而已。

此外,它的 GitHub 頁面也說,這不是一個功能完全健全的套件:

THIS IS UNSTABLE PROJECT, IF YOU WANT TO USE IT - FIX WHAT YOU NEED

講白了就是它有點陽春!

如果不打算安裝django-mongoengine,那就直接安裝mongoengine

1
pip install mongoengine

Django settings.py 設定

幾乎所有對 Django 整合的附加功能,都需要新增相關設定到專案的settings.py。MongoEngine 也不例外。

一、已安裝 Django-MongoEngine

上述第一個關於安裝 Django-MongoEngine 的好處,同時也是最大的好處,就是對於專案settings.py的直接整合,其設定大致如下:

1
2
3
4
5
6
7
8
MONGODB_DATABASES = {
"default": {
"name": database_name,
"host": database_host,
"password": database_password,
"username": database_user,
},
}

支援類似 Django 的DATABASES設定,名為MONGODB_DATABASES,要讓此設定生效,必須把django_mongoengine加入INSTALLED_APPS

1
2
3
4
5
6
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
...
'django_mongoengine',
]

二、未安裝 Django-MongoEngine

如果沒有安裝 Django-MongoEngine,則需要在settings.py新增下列設定:

1
2
3
4
from mongoengine import connect
...
...
connect(host="mongodb://127.0.0.1:27017/my_db")

只要這個connect函式可以在settings.py成功執行,Django app 就能成功取得對 MongoDB 的連線,進而存取資料庫。

這個寫法比較大的問題就是和settings.py其餘設定的模式格格不入,從程式碼風格一致性的角度來看,我並不推薦。不過使用上應該不會構成太大影響。

附帶一提:這個connect連線設定的參數有許多變化型態,可參考文件


本文只著眼於 MongoEngine 與 Django 的專案整合相關設定。至於實際使用與 ORM 查詢,比如DocumentField.objects等等,則會在接下來的文章中介紹。

參考