7.0 KiB
NoSQL (分散 / ビッグデータ) Databases
FastAPI はあらゆる NoSQLと統合することもできます。
ここではドキュメントベースのNoSQLデータベースである**Couchbase**を使用した例を見てみましょう。
他にもこれらのNoSQLデータベースを利用することが出来ます:
- MongoDB
- Cassandra
- CouchDB
- ArangoDB
- ElasticSearch など。
!!! tip "豆知識" FastAPIとCouchbaseを使った公式プロジェクト・ジェネレータがあります。すべてDockerベースで、フロントエンドやその他のツールも含まれています: https://github.com/tiangolo/full-stack-fastapi-couchbase
Couchbase コンポーネントの Import
まずはImportしましょう。今はその他のソースコードに注意を払う必要はありません。
{!../../../docs_src/nosql_databases/tutorial001.py!}
"document type" として利用する定数の定義
documentで利用する固定のtypeフィールドを用意しておきます。
これはCouchbaseで必須ではありませんが、後々の助けになるベストプラクティスです。
{!../../../docs_src/nosql_databases/tutorial001.py!}
Bucket を取得する関数の追加
Couchbaseでは、bucketはdocumentのセットで、様々な種類のものがあります。
Bucketは通常、同一のアプリケーション内で互いに関係を持っています。
リレーショナルデータベースの世界でいう"database"(データベースサーバではなく特定のdatabase)と類似しています。
MongoDB で例えると"collection"と似た概念です。
次のコードでは主に Bucket を利用してCouchbaseを操作します。
この関数では以下の処理を行います:
- Couchbase クラスタ(1台の場合もあるでしょう)に接続
- タイムアウトのデフォルト値を設定
- クラスタで認証を取得
Bucketインスタンスを取得- タイムアウトのデフォルト値を設定
- 作成した
Bucketインスタンスを返却
{!../../../docs_src/nosql_databases/tutorial001.py!}
Pydantic モデルの作成
Couchbaseのdocumentは実際には単にJSONオブジェクトなのでPydanticを利用してモデルに出来ます。
User モデル
まずはUserモデルを作成してみましょう:
{!../../../docs_src/nosql_databases/tutorial001.py!}
このモデルはpath operationに使用するのでhashed_passwordは含めません。
UserInDB モデル
それではUserInDBモデルを作成しましょう。
こちらは実際にデータベースに保存されるデータを保持します。
Userモデルの持つ全ての属性に加えていくつかの属性を追加するのでPydanticのBaseModelを継承せずにUserのサブクラスとして定義します:
{!../../../docs_src/nosql_databases/tutorial001.py!}
!!! note "備考"
データベースに保存されるhashed_passwordとtypeフィールドをUserInDBモデルに保持させていることに注意してください。
しかしこれらは(*path operation*で返却する)一般的な`User`モデルには含まれません
user の取得
それでは次の関数を作成しましょう:
- username を取得する
- username を利用してdocumentのIDを生成する
- 作成したIDでdocumentを取得する
- documentの内容を
UserInDBモデルに設定する
path operation関数とは別に、username(またはその他のパラメータ)からuserを取得することだけに特化した関数を作成することで、より簡単に複数の部分で再利用したりユニットテストを追加することができます。
{!../../../docs_src/nosql_databases/tutorial001.py!}
f-strings
f"userprofile::{username}" という記載に馴染みがありませんか?これは Python の"f-string"と呼ばれるものです。
f-stringの{}の中に入れられた変数は、文字列の中に展開/注入されます。
dict アンパック
UserInDB(**result.value)という記載に馴染みがありませんか?これはdictの"アンパック"と呼ばれるものです。
これはresult.valueのdictからそのキーと値をそれぞれ取りキーワード引数としてUserInDBに渡します。
例えばdictが下記のようになっていた場合:
{
"username": "johndoe",
"hashed_password": "some_hash",
}
UserInDBには次のように渡されます:
UserInDB(username="johndoe", hashed_password="some_hash")
FastAPI コードの実装
FastAPI app の作成
{!../../../docs_src/nosql_databases/tutorial001.py!}
path operation関数の作成
私たちのコードはCouchbaseを呼び出しており、実験的なPython awaitを使用していないので、私たちはasync defではなく通常のdefで関数を宣言する必要があります。
また、Couchbaseは単一のBucketオブジェクトを複数のスレッドで使用しないことを推奨していますので、単に直接Bucketを取得して関数に渡すことが出来ます。
{!../../../docs_src/nosql_databases/tutorial001.py!}
まとめ
他のサードパーティ製のNoSQLデータベースを利用する場合でも、そのデータベースの標準ライブラリを利用するだけで利用できます。
他の外部ツール、システム、APIについても同じことが言えます。