Python
 Computer >> コンピューター >  >> プログラミング >> Python

PyMongoでカスタムPythonオブジェクトをBSONとしてエンコードする方法

PyMongoでカスタムPythonオブジェクトをBSONとしてエンコードする方法

PyMongoを使ってカスタムPythonオブジェクトをBSON形式としてMongoDBに保存するには、SONManipulatorを作成する必要があります。公式ドキュメントでは、この仕組みについて次のように説明されています。

SONManipulatorのインスタンスを使用すると、PyMongoが自動的に適用する変換処理(トランスフォーメーション)を指定できます。つまり、オブジェクトの保存時(書き込み時)と取得時(読み込み時)に、それぞれ任意の変換ロジックを挿入できるのです。

SONManipulatorの実装例

以下は、カスタムクラスCustomのインスタンスを検出してエンコード・デコードするTransformクラスの実装例です。

from pymongo.son_manipulator import SONManipulator

class Transform(SONManipulator):
    def transform_incoming(self, son, collection):
        for (key, value) in son.items():
            if isinstance(value, Custom):
                son[key] = encode_custom(value)
            elif isinstance(value, dict):  # サブドキュメントにも再帰的に適用
                son[key] = self.transform_incoming(value, collection)
        return son

    def transform_outgoing(self, son, collection):
        for (key, value) in son.items():
            if isinstance(value, dict):
                if '_type' in value and value['_type'] == 'custom':
                    son[key] = decode_custom(value)
                else:  # こちらもサブドキュメントに再帰的に適用
                    son[key] = self.transform_outgoing(value, collection)
        return son

ポイントは、ネストされた辞書(サブドキュメント)の中にカスタムオブジェクトが含まれている場合でも正しく処理できるよう、再帰的に変換を適用している点です。

データベースオブジェクトへの登録方法

作成したマニピュレータは、次のようにPyMongoのデータベースオブジェクトに追加します。

db.add_son_manipulator(Transform())

これ以降、このデータベースに対するすべての読み書き操作に、自動的に変換処理が適用されるようになります。

_typeフィールドについての補足

なお、NumPy配列を暗黙的にPythonのリストへ変換したいだけであれば、_typeフィールドを追加する必要はありません。_typeフィールドは、取得時に元のカスタム型を識別して復元するための目印であり、単純な型変換のみを行う場合は不要だからです。

注意:PyMongo 4.0以降での変更点

SONManipulatorはPyMongo 4.0で削除されました。最新バージョンのPyMongoでは、代わりにbson.codec_options.TypeRegistryとカスタムコーデック(CodecOptions)を組み合わせることで、独自の型に対するエンコード・デコードを実現することが推奨されています。新規プロジェクトでは、TypeRegistryベースの実装を採用することをおすすめします。

  1. 【Python・Pandas】RangeIndexの作成方法を初心者向けに解説

    はじめにPandasでRangeIndexを作成するには、pandas.RangeIndex()メソッドを使用します。まず、必要なライブラリをインポートしましょう。import pandas as pdRangeIndexとは、Int64Indexの特殊なケースであり、単調な範囲(等差数列)のみを表現できる、メモリ消費を抑えられる軽量なインデックスです。RangeIndexを活用することで、状況によっては計算速度の向上も期待できます。RangeIndexの作成方法start(開始値)、stop(終了値)、step(増分)を指定して、範囲インデックスを作成します。name引数には、インデックスに

  2. PythonのBokehで画像を操作・表示する方法

    Pythonの可視化ライブラリBokehで画像を扱うには、image_url()メソッドを使い、画像URLのリストを渡すのが基本です。このメソッドを使うことで、ローカルやWeb上にある画像をプロット領域内に簡単に配置できます。実装の手順output_file()でデフォルトの出力先を設定し、show()を呼び出したときに結果がHTMLファイルとして保存されるようにします。figure()でプロット用の新しいFigure(図)オブジェクトを作成します。image_url()メソッドで、指定したURLから読み込んだ画像を描画します。show()を呼び出して、Bokehオブジェクトやアプリケーション