ウェブサイト検索

たった 1 行のコードを追加するだけで、MongoDB で Django を使用する方法。


シディ・ゼン著

MongoDB を Django プロジェクトのバックエンド データベースとして使用するには、settings.py ファイルに次の 1 行 を追加するだけです。

DATABASES = {   ‘default’: {      ‘ENGINE’: ‘djongo’,      ‘NAME’: ‘your-db-name’,   }}

それはとても簡単です!

次に、管理者ホーム (localhost:8000/admin/) にログインし、管理 GUI を使用して MongoDB への「埋め込みドキュメント」の追加を開始します。

2017 年 10 月、MongoDB は株式公開の最終段階を完了し、IPO の価格を 24 ドルに設定し、その過程で 1 億 9,200 万ドルを調達しました。会社の財務は着実に成長しています。

MongoDB は、オープンソースのデータベース ソフトウェアを提供します。これは、厳しい予算の制約を受けながら立ち上げを検討している初期段階のスタートアップにとって非常に役立ちます。 MongoDB に対する Google の検索トレンドを調査したところ、関心が着実に高まっていることが明らかになりました。

MongoDB は、使用するデータベース ソフトウェアとしてますます人気が高まっています。データベースとデータベース管理システム (DBMS) は 50 年以上前から存在しています。これらは 1960 年代初頭に登場し、最も人気のあるのはリレーショナル データベース システムでした。

しかし、MongoDB は自らを「非リレーショナル」データベース システムと呼び、データを保存するアプローチについて大げさな主張を行っています。では、ここでの大きな取引とは一体何でしょうか?

MongoDB と SQL

ほぼすべてのリレーショナル データベース システムは、構造化照会言語 (SQL) (またはその微調整版) を使用してデータ管理ソフトウェアと通信します。いくつかの大学のコースは、SQL 構文の理解と習得だけに特化しています。

SQL は、プロプライエタリまたはオープン ソースのあらゆるデータベース (DB) ソフトウェアを操作するための事実上の言語になりました。その後、MongoDB が登場し、この古代の強力な言語を完全に無視することを決定し、独自のクエリ構文を導入しました。

その言語はモルドールの言語ですが、ここでは述べません。俗語では、「一つの指輪がすべてを支配する。一つのリングでそれらを見つけられます。一つの指輪がそれらすべてをもたらし、暗闇の中でそれらを結びつける。 」

- ガンダルフ ( ロード・オブ・ザ・ リングから)

MongoDB スキーマレスと SQL スキーマ: SQL データベースでは、いわゆるスキーマでテーブルとフィールド タイプを定義するまでデータを追加することはできません。 MongoDB データベースでは、いつでもどこでもデータを追加できます。ドキュメントのデザインやコレクションを事前に指定する必要はありません。

MongoDB ドキュメントと SQL テーブルの比較: SQL データベースは、関連するデータ テーブルのストアを提供します。すべての行は異なるレコードです。設計は厳密です。同じテーブルを使用して異なる情報を保存したり、数値が必要な場所に文字列を挿入したりすることはできません。

MongoDB データベースには、JSON のようなフィールドと値のペアのドキュメントが保存されます。同様のドキュメントをコレクションに保存できます。コレクションは SQL テーブルに似ています。ただし、任意のデータを任意のドキュメントに保存できます。MongoDB は文句を言いません。 SQL テーブルは厳密なデータ テンプレートを作成するため、間違いが起こりにくくなります。 MongoDB はより柔軟で寛容ですが、あらゆるデータをどこにでも保存できるため、一貫性の問題が発生する可能性があります。

MongoDB は SQL のスーパーセットではないと主張するオンライン コンテンツが大量にあります。 SQL 上で実行されるアプリケーションを MongoDB に移植することはできません。ここで私は、Django のコンテキストにおいてはMongoDB は SQL のスーパーセットであると主張するために、大胆に主張します。

では、そもそも、なぜ MongoDB は SQL のスーパーセットではないという一般的な考えが存在するのでしょうか?

MongoDB ではデータの非正規化が必要です。 MongoDb では JOIN サポートがありません。これは、ドキュメントを非正規化する必要があることを意味します。非正規化ドキュメントによりクエリは高速化されますが、複数の非正規化ドキュメントのドキュメント フィールド情報の更新は大幅に遅くなります。

JOIN はありません: SQL クエリには強力な JOIN 句が用意されています。単一の SQL ステートメントを使用して、複数のテーブルの関連データを取得できます。 MongoDB のような非リレーショナル データベースには、リレーショナル データベースのような JOIN はありません。つまり、コード内で複数のクエリを実行し、データを手動で結合する必要があります。

トランザクションなし: SQL データベースでは、成功または失敗を保証する全か無かのラッパーであるトランザクションで 2 つ以上の更新を実行できます。 2 つの更新を個別に実行すると、1 つは成功し、もう 1 つは失敗する可能性があるため、数値が同期されなくなります。トランザクション内に同じ更新を配置すると、両方が成功するか両方が失敗するかのどちらかが保証されます。

外部キー制約なし: ほとんどの SQL データベースでは、外部キー制約を使用してデータ整合性ルールを適用できます。これにより、結合テーブル内の 1 つのエントリと一致するコードに対して有効な外部キーがすべての行にあることが保証され、1 つ以上の行がまだ参照している場合でも結合テーブルからレコードが削除されないことが保証されます。

スキーマは、データベースが従うべきこれらのルールを強制します。開発者やユーザーがレコードを追加、編集、削除することは不可能であり、無効なデータや孤立したレコードが発生する可能性があります。同じデータ整合性オプションは MongoDB では使用できません。他の書類に関係なく、必要なものを保管できます。理想的には、1 つのドキュメントがアイテムに関するすべての情報の唯一のソースになります。

データベースモデルの必要性

オブジェクトは、Python によるデータの抽象化です。 Python プログラム内のすべてのデータは、オブジェクトまたはオブジェクト間の関係によって表されます。オブジェクトはデータを表現する良い方法ですが、 データを永続的にしたい場合に問題が発生します。データの量は膨大になる可能性があるため、永続メモリから迅速かつ効率的にデータを取得する必要があります。オブジェクトを保存するには、このデータベース ソフトウェアを使用する必要があります。考えられるデータベース ソフトウェアは、リレーショナルの SQL ベースのデータベース ソフトウェアです。

オブジェクト リレーショナル マッパー (ORM) は、リレーショナル データベース テーブルに格納されているデータの、Python コードで使用される Python オブジェクトへの転送を自動化するコード ライブラリです。 ORM は、リレーショナル データベースに高レベルの抽象化を提供し、開発者が SQL 構文の代わりに Python コードを記述して、データベース内のデータとスキーマを作成、読み取り、更新、削除できるようにします。開発者は、SQL ステートメントやストアド プロシージャを作成する代わりに、使い慣れた Python プログラミング言語を使用できます。

Python の ORM フレームワークの例は SQLAlchemy です。 SQLAlchemy ORM は、ユーザー定義の Python クラスをデータベース テーブルに関連付け、それらのクラスのインスタンス (オブジェクト) を対応するテーブルの行に関連付ける方法を提供します。これには、オブジェクトとその関連行間の状態のすべての変更を透過的に同期するシステムが含まれています。 flask のような Web フレームワークは、データを永続的に保存するために SQLAlchemy を使用します。

Django ORM: Django には独自の ORM、略してモデルが付属しています。 モデルは、データに関する唯一の決定的な情報源です。これには、保存するデータの重要なフィールドと動作が含まれています。一般に、各モデルは単一のデータベース テーブルにマップされます。 Django モデルを使用すると、Oracle SQL、MySQL、MSSQL などのさまざまなリレーショナル データベース間の切り替えも可能になります。

Django ORM を使用して MongoDB にドキュメントを追加する

MongoDB をバックエンドとして Django を使用してブログ プラットフォームを作成したいとします。

ブログの app/models.py ファイルで、BlogContent モデルを定義します。

from djongo import modelsfrom djongo.models import forms
class BlogContent(models.Model):    comment = models.CharField(max_length=100)    author = models.CharField(max_length=100)    class Meta:        abstract = True

Django Admin を使用してモデルにアクセスするには、上記のモデルのフォーム定義が必要です。以下のように定義します。

class BlogContentForm(forms.ModelForm):    class Meta:        model = BlogContent        fields = (            'comment', 'author'        )

次に、以下のように EmbeddedModelField を使用して BlogContentBlogPost 内に「埋め込み」ます。

class BlogPost(models.Model):    h1 = models.CharField(max_length=100)    content = models.EmbeddedModelField(        model_container=BlogContent,        model_form=BlogContentForm    )   

これで準備完了です! localhost:8000/admin/ で Django Admin を起動すると、次の結果が得られます。

次に、作成者フィールドを「拡張」して、名前以外の情報も含めたいとします。名前とメールアドレスの両方が必要です。 author フィールドを「char」フィールドではなく「embedded」フィールドにするだけです。

class Author(models.Model):    name = models.CharField(max_length=100)    email = models.CharField(max_length=100)    class Meta:        abstract = Trueclass AuthorForm(forms.ModelForm):    class Meta:        model = Author        fields = (            'name', 'email'        )
class BlogContent(models.Model):    comment = models.CharField(max_length=100)    author = models.EmbeddedModelField(        model_container=Author,        model_form=AuthorForm    )    class Meta:        abstract = True

ブログ投稿に複数の作成者による複数のコンテンツが含まれている場合は、新しいモデルを定義します。

class MultipleBlogPosts(models.Model):    h1 = models.CharField(max_length=100)    content = models.ArrayModelField(        model_container=BlogContent,        model_form=BlogContentForm    )

新しい変更を加えて Django Admin を起動すると、次のようになります。

Django と MongoDB を統合する方法。

Django ORM は、互いに積み重ねられた複数の抽象化レイヤーで構成されます。

Web 開発者は、2 つの方法で Django を MongoDB に接続することに挑戦できます。上記の Django フレームワーク スタックを見て、考えられるエントリ ポイントを推測してください。

MongoDB互換モデルを使用する

プロジェクトで「バッテリーが付属した」Django モデルを使用することを完全に回避できます。代わりに、Django プロジェクトで MongoEngine や Ming などのサードパーティ フレームワークを使用してください。

別のモデルを選択すると、以下を逃すことになります。

  • プロジェクトへの 1500 人以上の中心的な貢献者
  • 時間ごとの修正とチケットの解決

既存の Django モデルの専門知識を少しずつ減らして、新しいモデル フレームワークを強化することになります。しかし、おそらく最大の欠点は、プロジェクトで Django の contrib モデルを使用できないことです。プロジェクトに Admin、Sessions、Users、Auth、その他の contrib モジュールを使用することは忘れてください。

これらの欠点の一部は、Django 自体の新しいブランチをフォークすることで相殺されます。 Django-nonrel は、Django に NoSQL データベースのサポートを追加する Django の独立したブランチです。 Django-nonrel を使用すると、ポータブルな Django アプリを作成できます。ただし、管理インターフェイスは完全には機能しません。 Django-nonrel プロジェクトでは積極的な開発は行われていません。

Django MongoDB Engine は、MongoEngine ODM からフォークされた、Django のもう 1 つの MongoDB バックエンドです。

Django SQL から MongoDB へのトランスパイラー — Djongo

もう 1 つのアプローチは、Django ORM によって生成された Django SQL クエリ構文を pymongo コマンドに変換することです。 Djongo は、SQL to MongoDB クエリ コンパイラーの 1 つです。すべての SQL クエリ文字列を mongoDB クエリ ドキュメントに変換します。その結果、すべての Django モデルと関連モジュールはそのまま動作します。このアプローチにより、次のメリットが得られます。

  • Django モデルの再利用: Django は、継続的な開発と機能強化を備えた安定したフレームワークです。 Django ORM は非常に広範で機能が豊富です。 MongoDB で動作するサードパーティの ORM を定義するということは、Django ORM 全体を再度再現することを意味します。新しい ORM は、Django ORM と常に調整する必要があります。いくつかの Django 機能は、サードパーティの ORM に組み込まれることはありません。 Djongo のアイデアは、最終的に SQL クエリを MongoDB 構文に変換することで、既存の Django ORM 機能を再利用することです。
  • Django に将来追加されるかどうかに関係なく、SQL 構文は決して変更されません。 Djongo を使用することで、プロジェクトは将来も保証されるようになります。

Django を MongoDB と連携させる

MongoDB でのスキーマのエミュレーション: MongoDB ではスキーマのサポートはありませんが、これはエミュレートできます。 Djongo は、MongoDB バリデーター ルールの組み合わせを使用および定義し、__schema__ コレクションを作成することにより、Django で必要なスキーマ サポートを提供します。 __schema__ コレクションには、SQL AUTOINCREMENT キーなどのサポート機能に関する情報が保存されます。

MongoDB での JOIN サポート: バージョン 3.2 では、MongoDB に $lookup 演算子が導入されました。同じデータベース内のコレクションに対して左外部結合を実行し、「結合された」コレクションからドキュメントをフィルタリングして処理します。 $lookup ステージは、入力ドキュメントのフィールドと「結合された」コレクションのドキュメントのフィールドとの間の等価一致を実行します。

$lookup ステージは、各入力ドキュメントに、「結合された」コレクションからの一致するドキュメントを要素とする新しい配列フィールドを追加します。 $lookup ステージは、これらの再形成されたドキュメントを次のステージに渡します。

Djongo は、$lookup 集計演算子を使用して、Django 関連のすべての JOIN クエリを実行します。これにより、admin および他の contrib モジュールがそのまま動作するようになります。

MongoDB でのトランザクション サポート: 単一ドキュメントのアトミック操作の能力にもかかわらず、複数ドキュメントのトランザクションが必要な場合があります。順次操作で構成されるトランザクションを実行する場合、特定の問題が発生します。つまり、1 つの操作が失敗した場合、トランザクション内の前の操作は前の状態に「ロールバック」する必要があります。つまり、「オール・オア・ナッシング」です。 」

複数ドキュメントのトランザクションが必要な場合、Djongo は 2 フェーズ コミット パターンを実装して、この種の複数ドキュメントの更新をサポートします。 2 フェーズ コミットを使用すると、データの一貫性が確保され、エラーが発生した場合でもトランザクション前の状態を回復できます。

ただし、Djongo には独自の妥協点があります。では、Django プロジェクトに Djongo を使用することを選択した場合の欠点は何でしょうか?

パフォーマンス: Django ORM は、複雑なオブジェクト操作を標準 SQL クエリ文字列に変換するという重労働を実行します。バックエンド データベースが SQL ベースの場合は、後処理をほとんど行わずに、このクエリ文字列を直接データベースに渡すことができます。ただし、Djongo では、クエリ文字列を MongoDB クエリ ドキュメントに変換する必要があります。

これには、ある程度の CPU サイクルが必要になります。しかし、余分な CPU サイクルが本当に問題である場合は、おそらく最初から Python を使用すべきではありません。

結論

Django を MongoDB と統合するいくつかの方法について説明しました。これを行うための MongoEngine やその他のバリアントについて説明したオンライン文献が多数見つかります。

私はこれを別の方法で可能にする新しいコネクタである Djongo に焦点を当てました。使い方は簡単で、わずか 1 行のコードを追加するだけで、SQL バックエンドから MongoDB への移行プロセスが非常に簡単になります。

関連記事