Docs Home → アプリケーションの開発 → Python ドライバー → PyMongo
よくある質問
項目一覧
- PyMongo はスレッドセーフか?
- PyMongo のフォーク安全性
- マルチプロセシングで PyMongo を使用できますか?
- PyMongo はクエリの結果を Pandora DataFrame としてロードできますか。
- PyMongo での接続プーリングの仕組み
- PyMongo がすべてのドキュメントに _id フィールドを追加する理由
- カーソルのタイムアウト値を変更するにはどうすればよいですか。
-
Decimal
インスタンスの保存方法 - PyMongo が
9.99
を9.9900000000000002
に変換する理由 - PyMongo はドキュメントに対して属性スタイルのアクセスをサポートしていますか?
- PyMongo は非同期フレームワークをサポートしていますか?
- PyMongo は Mod_wsgi で動作しますか?
- PyMongo は PythonAnywhere と連携しますか?
- ドキュメントを JSON にエンコードするには
- PyMongo は Python 3で動作が異なりますか。
- Python 2と Python 3間で選択したオブジェクト ID を共有できますか?
PyMongo はスレッドセーフか?
はい。 PyMongo はスレッドセーフで、スレッド アプリケーション用の組み込み接続プーリングを提供します。
PyMongo のフォーク安全性
いいえ fork()
メソッドを使用して新しいプロセスを作成する場合は、親プロセスから子プロセスにMongoClient
クラスのインスタンスを渡さないでください。 これにより、子プロセス内のMongoClient
インスタンス間でデッドロックが発生する可能性が高くなります。 代わりに、子プロセスに新しいMongoClient
インスタンスを作成します。
注意
このデッドロックが発生する可能性がある場合、PyMongo は警告の発行を試みます。
マルチプロセシングで 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
クラスのインスタンスを親プロセスから子プロセスにコピーしないでください。
PyMongo はクエリの結果を Pandora DataFrame としてロードできますか。
PyMongoArrowライブラリを使用して、数値データまたは列挙データを処理できます。 PyMongoArrow を使用すると、MongoDB クエリの結果セットを Panas Data Frames としてロードできます 、 NumPy 配列 、または Apache Arrow テーブル
PyMongo での接続プーリングの仕組み
すべての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 参照してください。
PyMongo がすべてのドキュメントに _id フィールドを追加する理由
Collection.insert_one()
メソッド、 Collection.insert_many()
メソッド、またはCollection.bulk_write()
メソッドを使用してドキュメントを MongoDB に挿入し、そのドキュメントに_id
フィールドが含まれていない場合、PyMongo はこのフィールドを自動的に追加します。 また、 フィールドの値をObjectId
のインスタンスに設定します。
次のコード例では、 _id
フィールドのないドキュメントを MongoDB に挿入し、そのドキュメントを出力します。 挿入後、ドキュメントには値がObjectId
のインスタンスである_id
フィールドが含まれます。
'x': 1} my_doc = { 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()
メソッドに渡します。
Decimal
インスタンスの保存方法
MongoDB v 3.4 は、正確な精度で小数の丸めをエミュレートできる128ビットの 10 進数ベースの浮動小数点値であるDecimal128
BSON 型を導入しました。 PyMongo バージョン3.4以降もこのタイプをサポートしています。 ただし、以前の MongoDB バージョンでは、Python float
型と同等の IEEE 754浮動小数点のみをサポートしています。 PyMongo は、 Decimal
インスタンスをこれらのバージョンの MongoDB に保存するには、 float
型に変換する必要があります。 この変換は明示的に実行する必要があります。
詳細については、 PyMongo API ドキュメントの 10 進数128 を参照してください。
PyMongo が9.99
を9.9900000000000002
に変換する理由
MongoDB は9.99
を IEEE 浮動小数点値として表しますが、値を正確に表すことはできません。 これは、Python の一部のバージョンにも当てはまります。 この点で、PyMongo は JavaScript shell、他のすべての MongoDB ドライバー、および Python 言語自体と同じように動作します。
PyMongo はドキュメントに対して属性スタイルのアクセスをサポートしていますか?
いいえ。PyMongo は次の理由で、この機能を実装していません。
属性を追加すると、ドキュメントの属性名前空間が破損し、辞書メソッドと同じ名前のキーを使用すると、若干のバグや混乱するエラーが発生する可能性があります。
PyMongo は、サーバーが特定の操作でこれを必要とするため、通常の辞書ではなく SON オブジェクトを使用します。 この機能を追加すると、
SON
クラスが複雑になり、PyMongo が辞書を使用するように戻った場合には、下位互換性が失われる可能性があります。ドキュメントは辞書と同様に動作するため、PyMongo の新規ユーザーにとっては比較的簡単に理解できます。 ドキュメントの動作を変更すると、これらのユーザーのエントリへの障害が生じます。
詳細については、関連する Jira ケースを参照してください。
PyMongo は非同期フレームワークをサポートしていますか?
はい。 詳細については、サードパーティ ツール のガイドを参照してください。
PyMongo は Mod_wsgi で動作しますか?
はい。ツール ガイドのMod_wsgiを参照してください。
PyMongo は PythonAnywhere と連携しますか?
いいえ。PyMongo は Python スレッドを作成します。Python は PythonAnywhere は、 をサポートしていません。
詳しくは、関連する Jira チケットを参照してください。
ドキュメントを JSON にエンコードするには
PyMongo は、 ObjectId
やDBRef
など、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 は Python 3で動作が異なりますか。
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と Python 3間で選択したオブジェクト ID を共有できますか?
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() oidObjectId('4f919ba2fba5225b84000000') pickle.dumps(oid)'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...' # Python 3.7 import pickle b'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...', encoding='latin-1') pickle.loads(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() oidObjectId('4f96f20c430ee6bd06000000') 2) pickle.dumps(oid, protocol=b'\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...' # Python 2.7 import pickle '\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...') pickle.loads(ObjectId('4f96f20c430ee6bd06000000')