Docs Menu

Docs Homeアプリケーションの開発Python ドライバーPyMongo

よくある質問

項目一覧

はい。 PyMongo はスレッドセーフで、スレッド アプリケーション用の組み込み接続プーリングを提供します。

いいえ fork()メソッドを使用して新しいプロセスを作成する場合は、親プロセスから子プロセスにMongoClientクラスのインスタンスを渡さないでください。 これにより、子プロセス内のMongoClientインスタンス間でデッドロックが発生する可能性が高くなります。 代わりに、子プロセスに新しいMongoClientインスタンスを作成します。

注意

このデッドロックが発生する可能性がある場合、PyMongo は警告の発行を試みます。

はい。 ただし、Unix システムでは、マルチプロセシング モジュールはfork()メソッドを使用してプロセスを生成します。 これには、 PyMongo forkが安全か?で説明されているのと同じリスクが伴います。

PyMongo でマルチプロセシングを使用するには、次の例のようなコードを記述します。

# Each process creates its own instance of MongoClient.
def func():
db = pymongo.MongoClient().mydb
# Do something with db.
proc = multiprocessing.Process(target=func)
proc.start()

重要

MongoClientクラスのインスタンスを親プロセスから子プロセスにコピーしないでください。

PyMongoArrowライブラリを使用して、数値データまたは列挙データを処理できます。 PyMongoArrow を使用すると、MongoDB クエリの結果セットを Panas Data Frames としてロードできます NumPy 配列 、または Apache Arrow テーブル

すべてのMongoClientインスタンスには、MongoDB トポロジー内の各サーバーに対する接続プールが組み込まれています。 接続プールはオンデマンドでソケットを開き、アプリケーション内の MongoDB への同時要求をサポートします。

各接続プールの最大サイズはmaxPoolSizeオプションによって設定され、デフォルトは100になります。 サーバーへの使用中の接続数がmaxPoolSizeの値に達した場合、そのサーバーへの次のリクエストは、接続が利用可能になるまで待機します。

アプリケーションのリクエストをサポートするために必要なソケットに加えて、各MongoClientインスタンスは、サーバーの状態を監視するために MongoDB トポロジー内のサーバーごとにさらに 2 つのソケットを開きます。 たとえば、3 ノードのレプリカセットに接続されたクライアントは、6 つの監視ソケットを開きます。 アプリケーションがmaxPoolSizeのデフォルト設定を使用し、プライマリ(デフォルト)ノードのみをクエリする場合、接続プールには最大106の接続が存在できます。 アプリケーションが 読み込み設定( read preference ) を使用してセカンダリ ノードをクエリすると、それらの接続プールが大きくなり、合計接続数が306になる可能性があります。

1 つのプロセス内で多数の同時 MongoDB リクエストをサポートするには、 maxPoolSizeを増やすことができます。

接続プールにはレート制限があります。 maxConnectingオプションによって、プールが並行して作成できる接続数が決定されます。 たとえば、 maxConnectingの値が2の場合、接続を同時にチェックアウトしようとする 3 番目のリクエストは、次のいずれかの場合にのみ成功します。

  • 接続プールは接続の作成を完了し、プール内の接続数はmaxPoolSize未満です。

  • 既存の接続がプールにチェックバックされます。

  • 接続作成のレート制限により、既存の接続を再利用するドライバーの能力が向上します。

minPoolSizeオプションを使用して、各サーバーへの同時接続の最小数を設定できます。デフォルトは0になります。 ドライバーは、このソケット数で接続プールを初期化します。 ソケットが閉じられ、ソケットの合計数(使用中とアイドル状態の両方)が最小値を下回る場合、最小値に達するまでさらにソケットが開かれます。

maxIdleTimeMSオプションを設定することで、プール内で接続がアイドル状態を維持できる最大ミリ秒数を設定できます。 maxIdleTimeMSの接続がアイドル状態になると、接続プールはそれを削除し、置き換えます。 このオプションのデフォルトは0 (制限なし)です。

MongoClientの次のデフォルト構成はほとんどのアプリケーションで動作します。

client = MongoClient(host, port)

MongoClient は、複数の同時リクエストをサポートします。 プロセスごとにクライアントを作成し、プロセス内のすべての操作で再利用します。 この方法は、リクエストごとにクライアントを作成するよりも効率的です。

ドライバーはソケットが利用可能になるまで待機できるリクエストの数を制限しません。負荷が急増したときにプールのサイズを境界のあるキューに制限するのはアプリケーションの責任です。 リクエストは、 waitQueueTimeoutMSオプションで指定された時間だけ待機します。デフォルトでは0 (制限なし)です。

ソケットを対象にwaitQueueTimeoutMSで定義された時間以上待機するリクエストでは、 ConnectionFailureエラーが発生します。 すべての操作を完了することよりも、負荷急増中に操作の継続時間を制限することが重要な場合は、このオプションを使用します。

任意のリクエストによってMongoClient.close()が呼び出されると、ドライバーはすべてのアイドル ソケットを閉じ、プールに返されるときに使用中のすべてのソケットを閉じます。 MongoClient.close()を呼び出すと非アクティブなソケットのみが閉じられるため、このメソッドを使用して実行中の操作を中断したり終了したりすることはできません。 ドライバーはこれらのソケットを、プロセスが完了した場合にのみ閉じます。

詳細については、 のドキュメントの 管理/接続プール-オーバービュー/をMongoDB Server 参照してください。

Collection.insert_one()メソッド、 Collection.insert_many()メソッド、またはCollection.bulk_write()メソッドを使用してドキュメントを MongoDB に挿入し、そのドキュメントに_idフィールドが含まれていない場合、PyMongo はこのフィールドを自動的に追加します。 また、 フィールドの値をObjectIdのインスタンスに設定します。

次のコード例では、 _idフィールドのないドキュメントを MongoDB に挿入し、そのドキュメントを出力します。 挿入後、ドキュメントには値がObjectIdのインスタンスである_idフィールドが含まれます。

>>> my_doc = {'x': 1}
>>> collection.insert_one(my_doc)
InsertOneResult(ObjectId('560db337fba522189f171720'), acknowledged=True)
>>> my_doc
{'x': 1, '_id': ObjectId('560db337fba522189f171720')}

PyMongo がこのように_idフィールドを追加するのには次の理由があります。

  • すべての MongoDB ドキュメントには_idフィールドが必要です。

  • PyMongo が_idフィールドのないドキュメントを挿入した場合、MongoDB は自分自身を追加しますが、アプリケーションが使用するために PyMongo に値を報告することはありません。

  • _idフィールドを追加する前にドキュメントをコピーすることは、ほとんどの高書込み保証(write concern)アプリケーションではコストが高すぎる。

Tip

PyMongo でドキュメントに_idを追加しない場合は、アプリケーションがすでに_idフィールドを追加しているドキュメントのみを挿入します。

MongoDB はカーソルのカスタム タイムアウトをサポートしていませんが、カーソルのタイムアウトをオフにすることはできます。 そのためには、 no_cursor_timeout=Trueオプションをfind()メソッドに渡します。

MongoDB v 3.4 は、正確な精度で小数の丸めをエミュレートできる128ビットの 10 進数ベースの浮動小数点値であるDecimal128 BSON 型を導入しました。 PyMongo バージョン3.4以降もこのタイプをサポートしています。 ただし、以前の MongoDB バージョンでは、Python float型と同等の IEEE 754浮動小数点のみをサポートしています。 PyMongo は、 Decimalインスタンスをこれらのバージョンの MongoDB に保存するには、 float型に変換する必要があります。 この変換は明示的に実行する必要があります。

詳細については、 PyMongo API ドキュメントの 10 進数128 を参照してください。

MongoDB は9.99を IEEE 浮動小数点値として表しますが、値を正確に表すことはできません。 これは、Python の一部のバージョンにも当てはまります。 この点で、PyMongo は JavaScript shell、他のすべての MongoDB ドライバー、および Python 言語自体と同じように動作します。

いいえ。PyMongo は次の理由で、この機能を実装していません。

  1. 属性を追加すると、ドキュメントの属性名前空間が破損し、辞書メソッドと同じ名前のキーを使用すると、若干のバグや混乱するエラーが発生する可能性があります。

  2. PyMongo は、サーバーが特定の操作でこれを必要とするため、通常の辞書ではなく SON オブジェクトを使用します。 この機能を追加すると、 SONクラスが複雑になり、PyMongo が辞書を使用するように戻った場合には、下位互換性が失われる可能性があります。

  3. ドキュメントは辞書と同様に動作するため、PyMongo の新規ユーザーにとっては比較的簡単に理解できます。 ドキュメントの動作を変更すると、これらのユーザーのエントリへの障害が生じます。

詳細については、関連する Jira ケースを参照してください。

はい。 詳細については、サードパーティ ツール のガイドを参照してください。

はい。ツール ガイドのMod_wsgiを参照してください。

いいえ。PyMongo は Python スレッドを作成します。Python は PythonAnywhere は、 をサポートしていません。

詳しくは、関連する Jira チケットを参照してください。

PyMongo は、 ObjectIdDBRefなど、JSON ではサポートされていない特殊な型を一部サポートしています。 そのため、Python のjsonモジュールは PyMongo 内のすべてのドキュメントでは動作しません。 代わりに、PyMongo には json_uty jsonモジュールは、BSON ドキュメントと MongoDB 拡張 JSON で Python の モジュールを使用するためのツールです。

python-bsonjs は、 libbson 上に構築された別の BSON から MongoDB 拡張 JSON への変換です 。python-bsonjs は PyMongo に依存しておらず、場合によってはjson_utilよりもパフォーマンスが向上する可能性があります。

Tip

python-bsonjs は、 RawBSONDocument型を使用する場合に PyMongo で最も動作します。

PyMongo は、 bytesクラスのインスタンスを BSON 型5 (バイナリ データ)としてサブタイプ0としてエンコードします。 Python 2では、これらのインスタンスはサブタイプ0を持つBinaryにデコードされます。 Python 3では、 bytesにデコードされます。

次のコード例では、PyMongo を使用してbytesインスタンスを MongoDB に挿入し、 インスタンスを検索します。 Python 2では、バイト string はBinaryにデコードされます。 Python 3では、バイト string はbytesにデコードされます。

同様に、PyMongo がサブタイプ0の JSON バイナリ値を解析する場合、Python 2と3の動作は異なります。 Python 2では、これらの値はサブタイプ0を持つBinaryのインスタンスにデコードされます。 Python 3では、 bytesのインスタンスにデコードされます。

次のコード例では、 json_utilモジュールを使用して、サブタイプ0の JSON バイナリ値をデコードします。 Python 2では、バイト string はBinaryにデコードされます。 Python 3では、バイト string はbytesにデコードされます。

Python 2を使用してObjectIdのインスタンスを選択した場合、Python 3を使用するといつでも選択を解除できます。 そのためには、 encoding='latin-1'オプションをpickle.loads()メソッドに渡す必要があります。 次のコード例は、Python 2.7でObjectIdを選択し、Python 3.7で選択解除する方法を示しています。

# Python 2.7
>>> import pickle
>>> from bson.objectid import ObjectId
>>> oid = ObjectId()
>>> oid
ObjectId('4f919ba2fba5225b84000000')
>>> pickle.dumps(oid)
'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...'
# Python 3.7
>>> import pickle
>>> pickle.loads(b'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...', encoding='latin-1')
ObjectId('4f919ba2fba5225b84000000')

Python 2でObjectIDを選択し、 かつ Python 3で選択解除する場合は、 2以下の値を持つprotocol引数をpickle.dumps()メソッドに渡す必要があります。 次のコード例は、Python 3.7でObjectIdを選択し、Python 2で選択解除する方法を示しています。 7 :

# Python 3.7
>>> import pickle
>>> from bson.objectid import ObjectId
>>> oid = ObjectId()
>>> oid
ObjectId('4f96f20c430ee6bd06000000')
>>> pickle.dumps(oid, protocol=2)
b'\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...'
# Python 2.7
>>> import pickle
>>> pickle.loads('\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...')
ObjectId('4f96f20c430ee6bd06000000')
← サードパーティ ツール