重要なアプリケーションを構築する場合は、本番環境で発生する可能性のある予期しないイベントに備えることが重要です。 これには、予期しない低速クエリ、インデックスの欠落、またはワークロード量の急増が含まれます。
MongoDB Atlasは、先を見越して準備し、状況に対応できるようにする既存の機能を提供することで、回復力のあるアプリケーションを構築するのに役立ちます。 回復力のあるアプリケーションを構築するには、次のクラスター回復力とアプリケーション、およびクライアント側のベストプラクティスを使用してMongoDBデプロイを構成することをお勧めします。
クラスターの回復力
クラスターの回復力を向上させるには、クラスターをMongoDB 8.0にアップグレードします。 MongoDB 8.0では、回復力に関連する次のパフォーマンスの向上と新機能が導入されています。
コストのかかるクエリをリアクティブに軽減する操作拒否フィルター
コストのかかる読み取り操作に対するプロアクティブな保護のためのクラスターレベルのタイムアウト
moveCollection コマンドによるワークロードのより優れた分離
メモリ管理の改善
To run your application safely in production, it's important to ensure that your memory utilization allows for headroom. If a node runs out of available memory, it can become susceptible to the Linux Out of Memory Killer that terminates the mongod process.
MongoDB 8.0はアップグレードされた TCMallocをすべての配置に自動的に使用するため、平均的なメモリ フラグメントの増加が時間の経過とともに減少します。 フラグメント度が低いことで、ピーク負荷時の動作安定性が向上し、メモリ使用率が全体的に向上します。
操作拒否フィルター
意図しないリソース集中操作は、迅速に処理されない場合、本番環境で問題が発生する可能性があります。
MongoDB 8.0では、操作拒否フィルターを使用して、これらの操作の影響を最小限に抑えることができます。 操作拒否フィルターを使用すると、そのクエリシェイプでクエリを再度有効にするまで、実行中中のクエリを拒否するようにMongoDBを構成できます。
つまり、低速クエリを特定したら、アプリケーションチームが低速クエリの影響を軽減するためにクエリを修正するのを待つ必要はありません。 代わりに、クエリプロファイラー、リアルタイム パフォーマンス パネル、またはクエリ ログのいずれかでクエリのパフォーマンスが低下していることに気付いたら、そのクエリシェイプに 拒否フィルター を設定できます。 その後、 MongoDBはその受信クエリシェイプの新しいインスタンスが実行されないようにします。 クエリを修正したら、クエリシェイプを再度有効にできます。
次の場合は、操作拒否フィルターを使用する必要があります。
修正の進行中に低速クエリの影響を迅速に排除します。
過負荷時は、重要でないクエリを拒否して、より重要なワークロードを優先します。
最大リソース使用率に近い場合は、クラスターに時間を与えて回復します。
Atlas UIでの低速クエリの識別と拒否
Atlas UIで操作拒否フィルターを使用するには、次の手順に従います。
Atlas で、プロジェクトの [Clusters] ページに移動します。
まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー
まだ表示されていない場合は、ナビゲーション バーのProjectsメニューから目的のプロジェクトを選択します。
サイドバーで、 Database見出しの下のClustersをクリックします。
[ Clusters (クラスター) ] ページが表示されます。
現在のプロジェクト内の指定されたクラスターのクエリプロファイラーにGo。
クラスターの名前をクリックすると、Cluster サイドバーが開きます。
Cluster サイドバーで Query Insights をクリックします。
[Query Profiler] タブをクリックします。
特定のクエリシェイプの操作を拒否します。
Use setQuerySettings in your db.adminCommand() method to pass in the queryShapeHash, which specifies the query shape you want to reject.
注意
You must have the atlasAdmin role to use setQuerySettings.
拒否またはタイムアウト後にクエリを監視する
クラスター サイドバーの メトリクス で、クエリがその後実行される方法をモニターできます。
Atlas で、プロジェクトの [Clusters] ページに移動します。
まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー
まだ表示されていない場合は、ナビゲーション バーのProjectsメニューから目的のプロジェクトを選択します。
サイドバーで、 Database見出しの下のClustersをクリックします。
[ Clusters (クラスター) ] ページが表示されます。
読み取り操作のクラスターレベルのタイムアウト
本番環境に到達する前に、開発プロセスでクエリの効率を慎重に検討することが重要です。 例外は常に発生する可能性がありますが、非効率的なクエリに対して先を見越して軽減することで、クラスターのパフォーマンスの問題を防ぐことができます。
With MongoDB 8.0, you can protect your queries from unindexed operations with the server-side defaultMaxTimeMS coming into the cluster. If an operation exceeds this timeout, MongoDB cancels the operation to prevent queries from running too long and holding on to resources. This allows you to:
タイムアウトを設定する責任を、個々のアプリケーションチームからデータベースフォーカス チームに移行します。
クエリにインデックスがない場合のコレクションスキャンの影響を最小限に抑えます。
コストのかかる操作に対して最後のラウンドの軽減を用意することで、本番環境に移行します。
分析クエリなど、異なるタイムアウトを必要とするクエリがある場合は、 maxTimeMSメソッドで操作レベルのタイムアウトを設定することで、それらを上書きできます。
Atlas Administration APIで読み取り操作のデフォルト タイムアウトを設定する
To set the defaultMaxTimeMS parameter through the Atlas Administration API, see Update Advanced Configuration Options for One Cluster.
Atlas UIでの読み取り操作のデフォルト タイムアウトの設定
To set the defaultMaxTimeMS parameter in the Atlas UI:
Atlas で、プロジェクトの [Clusters] ページに移動します。
まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー
まだ表示されていない場合は、ナビゲーション バーのProjectsメニューから目的のプロジェクトを選択します。
サイドバーで、 Database見出しの下のClustersをクリックします。
[ Clusters (クラスター) ] ページが表示されます。
設定オプションに移動します。
既存のクラスターがある場合は、[ クラスターの編集 ]ページに移動します。
新しいクラスターを作成している場合は、 Select a versionドロップダウンから [ MongoDB 8.0 ] を選択します。
[Additional Settings] をクリックします。
下にスクロールしてMore Configuration Options ] をクリックします。
To view the behavior of killed operations, see Monitor Your Queries After Rejection or Timeout. To learn more, see defaultMaxTimeMS and Set Default Timeout for Read Operations.
シャーディングされていないコレクションの影響を分離する
シャー増やすにより、クラスターを水平方向にスケーリングできます。 MongoDBを使用すると、一部のコレクションをシャーディングしながら、同じクラスター内の他のコレクションはシャーディングされないままにできます。 新しいデータベースを作成すると、クラスター内のデータ量が最も少ないシャードがデフォルトでそのデータベースのプライマリシャードとして選択されデフォルト。 そのデータベースのシャーディングされていないコレクションは、デフォルトでそのプライマリシャードに配置されます。 これにより、特にワークロードロードの増加がプライマリシャードのシャーディングされていないコレクションに集中する場合、ワークロードの増加に伴いプライマリシャードへのトラフィックが増加する可能性があります。
To distribute this workload better, MongoDB 8.0 allows you to move an unsharded collection to other shards from the primary shard with the moveCollection command. This allows you to place active, busy collections onto shards with less expected resource usage. With this, you can:
大規模で複雑なワークロードのパフォーマンスを最適化します。
リソース使用率の向上を実現します。
シャード間で日付をより均等に分散します。
次の状況では、コレクションを分離することをお勧めします。
高スループットのシャーディングされていないコレクションが複数あるためにプライマリシャードに重大なワークロードが発生した場合。
シャーディングされていないコレクションでは将来、増加が予想され、他のコレクションのボトルネックになる可能性があります。
クラスターごとに 1 コレクションの配置設計を実行中していて、優先順位やワークロードに基づいてそれらのカスタマーを分離したいと考えています。
シャードには、シャーディングされていないコレクションの数が含まれているため、データ量が按分されています。
To learn how to move an unsharded collection with mongosh, see Move a Collection.
アプリケーションとクライアント側のベストプラクティス
MongoDB 配置とドライバー ライブラリの機能を構成して、ネットワーク停止やフェイルオーバー イベントに耐性のあるアプリケーションを作成できます。 MongoDB Atlas の 常時オン 機能を活用するアプリケーション コードを作成するには、次のタスクを実行する必要があります。
アプリケーション に適した
majorityの書込み保証 (write concern)と読み取り保証 (read concern)を使用しアプリケーション。アプリケーション内のエラーを処理します。
最新のクライアント ライブラリのインストール
MongoDBクライアント ライブラリから、ご使用の言語の最新のクライアントライブラリをインストールします。クライアント ライブラリは、アプリケーションからのクエリをデータベースに接続して中継します。最新のクライアントライブラリを使用すると、最新のMongoDB機能が有効になります。
次に、アプリケーションに依存関係をインポートします。
If you are using Maven, add the following to your pom.xml dependencies list:
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>4.0.1</version> </dependency> </dependencies>
If you are using Gradle, add the following to your build.gradle dependencies list:
dependencies { compile 'org.mongodb:mongodb-driver-sync:4.0.1' }
// Latest 'mongodb' version installed with npm const MongoClient = require('mongodb').MongoClient;
# Install the latest 'pymongo' version with pip and # import MongoClient from the package to establish a connection. from pymongo import MongoClient
接続文字列
注意
Atlasには、事前構成された接続文字列が用意されています。 事前構成された string をコピーする手順については、「 Atlas が提供する接続文字列 」を参照してください。
クラスター内のすべてのノードを指定する 接続文字列Atlas を使用して、アプリケーションをデータベースに接続します。クラスターでレプリカセットの選挙が実行され、新しいプライマリが選択された場合、クラスター内のすべてのノードを指定する接続文字列は、アプリケーション ロジックなしで新しいプライマリを検出します。
次のいずれかを使用して、クラスター内のすべてのノードを指定できます。
標準接続文字列形式、または
DNS シードリスト接続形式(Atlas で推奨)。
接続文字列では、オプション( retryWritesとwriteConcern など)を指定することもできます。
Atlas は、プライベートエンドポイント サービスのロード バランサーを使用して、シャーディングされたクラスター用に最適化された SRV 接続文字列を生成できます。最適化された接続文字列を使用する場合、Atlas はアプリケーションとシャーディングされたクラスター間の各 mongos の接続数を制限します。mongos ごとに接続数を制限することで、接続数が急増した際のパフォーマンスが向上します。
プライベートエンドポイントの背後にあるシャーディングされたクラスターに最適化された接続文字列の詳細については、プライベートエンドポイントを使用してシャーディングされたクラスターの接続パフォーマンスを最適化するにはどうすればよいですか。
Atlas が提供する接続文字列
Atlas クラスター インターフェースから接続文字列をコピーする場合、接続文字列 はクラスター用に事前構成され、DNS シードリスト形式を使用し、回復力のために推奨されるretryWrites とw (書込み保証(write concern))オプションが含まれます。
Atlas から接続文字列 URI をコピーするには、次の手順に従います。
Atlas で、プロジェクトの [Clusters] ページに移動します。
まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー
まだ表示されていない場合は、ナビゲーション バーのProjectsメニューから目的のプロジェクトを選択します。
サイドバーで、 Database見出しの下のClustersをクリックします。
[ Clusters (クラスター) ] ページが表示されます。
接続文字列 URI をコピーします。
接続文字列またはドライバー全体のサンプルをアプリケーション コードにコピーします。 データベースユーザーの認証情報を提供する必要があります。
注意
This guide uses SCRAM authentication through a connection string. To learn about using X.509 certificates to authenticate, see X.509.
接続文字列を使用して、アプリケーション内で MongoDB クライアントをインスタンス化します。
// Copy the connection string provided by Atlas String uri = <your Atlas connection string>; // Instantiate the MongoDB client with the URI MongoClient client = MongoClients.create(uri);
// Copy the connection string provided by Atlas const uri = <your Atlas connection string>; // Instantiate the MongoDB client with the URI const client = new MongoClient(uri);
# Copy the connection string provided by Atlas uri = <your Atlas connection string> # Pass your connection string URI to the MongoClient constructor client = MongoClient(uri)
再試行可能な書込みと読み取り
注意
MongoDB はデフォルトで書込みと読み取りの両方を 1 回再試行します。
再試行可能な書き込み
Use retryable writes to retry certain write operations a single time if they fail. If you copied your connection string from Atlas, it includes "retryWrites=true". If you are providing your own connection string, include "retryWrites=true" as a query parameter.
書き込みを 1 回だけ 再試行する ことは、アプリケーションが正常な プライマリ ノード を一時的に見つけられない場合に、一時的なネットワークエラーやレプリカセットの選挙を処理するための最善の戦略です。 再試行が成功すると、操作全体が成功し、エラーは返されません。 操作が失敗した場合は、次の理由が原因で失敗した可能性があります。
永続的なネットワークエラー
無効なコマンド
操作が失敗した場合、アプリケーションは自分自身を処理する必要があります。
再試行可能な読み取り
読み取り操作は、失敗すると 1 回自動的に再試行されます。読み取りを再試行するために追加の構成は必要ありません。
書込み保証 (write concern) と読み取り保証 (read concern)
書込み保証 (write concern) と読み取り保証 (read concern) を使用して、アプリケーションの整合性と可用性を調整できます。 懸念が深い場合は、データベース操作により強力なデータ整合性保証が必要になりますが、整合性要件を緩和すると可用性が向上します。
例
アプリケーションが金銭の残高を処理する場合、整合性は非常に重要です。 majorityの書込み保証と読み取り保証を使用して、古いデータやロールバックされる可能性のあるデータからの読み取りを行わないようにできます。
あるいは、アプリケーションが 1 秒ごとに数百のセンサーからの温度データを記録する場合、最新の読み取り値を含まないデータを読み取る場合は問題が発生しない場合があります。 整合性要件を緩和して、そのデータへのアクセスをより速くできます。
書込み保証 (write concern)
You can set the write concern level of your Atlas replica set through the connection string URI. Use a majority write concern to ensure your data is successfully written to your database and persisted. This is the recommended default and sufficient for most use cases. If you copied your connection string from Atlas, it includes "w=majority".
majorityなど、確認応答が必要な書込み保証を使用する場合は、そのレベルの確認応答を実現するための書込みの最大時間制限を指定することもできます。
すべての書き込み (write) のwtimeoutMS接続文字列パラメータ、または
単一の書込み (write) 操作のwtimeoutオプション。
時間制限を使用するかどうかと使用する値は、アプリケーションのコンテキストによって異なります。
重要
書込み (write) に時間制限を指定せず、書込み保証 (write concern) レベルが達成できない場合、書込み (write) 操作は無期限にハングします。
読み取り保証(read concern)
You can set the read concern level of your Atlas replica set through the connection string URI. The ideal read concern depends on your application requirements, but the default is sufficient for most use cases. No connection string parameter is required to use default read concerns.
読み取り保証を指定すると、アプリケーションが Atlas から受信するデータの保証が強化されます。
注意
アプリケーションが使用する書込み保証 (write concern) と読み取り保証 (read concern) の特定の組み合わせは、操作順序の保証に影響します。 これは 因果整合性 と呼ばれます。 因果整合性の保証の詳細については、「因果整合性、読み取り保証、書込み保証 」を参照してください。
Error Handling
再試行可能な書き込みで処理されていないコマンド、ネットワークの停止、ネットワークエラーはエラーを返します。 エラーの詳細については、ドライバーのAPIドキュメントを参照してください。
たとえば、アプリケーションが、データベースの コレクションで既に使用されている_id値を含むドキュメントを挿入しようとすると、ドライバーは次のようなエラーを返します。
Unable to insert due to an error: com.mongodb.MongoWriteException: E11000 duplicate key error collection: <db>.<collection> ...
{ "name": : "MongoError", "message": "E11000 duplicate key error collection on: <db>.<collection> ... ", ... }
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: <db>.<collection> ...
適切なエラー処理を行わないと、エラーによってアプリケーションが再起動されるまでリクエストの処理がブロックされる可能性があります。
アプリケーションは、クラッシュしたり副作用のないエラーを処理する必要があります。 コレクションに重複する_idを挿入するアプリケーションの以前の例では、そのアプリケーションは次のようにエラーを処理できます。
// Declare a logger instance from java.util.logging.Logger private static final Logger LOGGER = ... ... try { InsertOneResult result = collection.insertOne(new Document() .append("_id", 1) .append("body", "I'm a goofball trying to insert a duplicate _id")); // Everything is OK LOGGER.info("Inserted document id: " + result.getInsertedId()); // Refer to the API documentation for specific exceptions to catch } catch (MongoException me) { // Report the error LOGGER.severe("Failed due to an error: " + me); }
... collection.insertOne({ _id: 1, body: "I'm a goofball trying to insert a duplicate _id" }) .then(result => { response.sendStatus(200) // send "OK" message to the client }, err => { response.sendStatus(400); // send "Bad Request" message to the client });
... try: collection.insert_one({ "_id": 1, "body": "I'm a goofball trying to insert a duplicate _id" }) return {"message": "User successfully added!"} except pymongo.errors.DuplicateKeyError as e: print ("The insert operation failed:", e)
この例の挿入操作では、 _idフィールドが一意である必要があるため、2 回目に呼び出されるときに「重複キー」エラーがスローされます。 エラーがキャッチされ、クライアントに通知され、アプリは実行を続行します。 しかし、挿入操作は失敗します。ユーザーに メッセージを表示するか、操作を再試行するか、または別の操作を実行するかは、ユーザーが決定する必要があります。
エラーは常にログに記録する必要があります。 これ以上の処理エラーを発生させる一般的な戦略は次のとおりです。
エラーを、エラー メッセージとともにクライアントに返します。 これは、エラーを解決できず、アクションが完了できないことをユーザーに通知する必要がある場合に適した戦略です。
バックアップ データベースに書き込みます。 これは、エラーを解決できないが、リクエスト データが失われるリスクを避けたい場合に適した戦略です。
操作を1 回のデフォルトの 再試行 を超えて再試行します。 これは、エラーの原因をプログラムで解決して再試行する場合に適した戦略です。
アプリケーションのコンテキストに最適な戦略を選択する必要があります。
例
重複キー エラーの例では、エラーをログに記録する必要がありますが、操作は成功しないため、再試行しないでください。 代わりに、フォールバック データベースに書き込みを行い、後でそのデータベースの内容を確認して、情報が失われることを確認することができます。 ユーザーは他に何もする必要がなく、データが記録されるため、クライアントにエラーメッセージを送信しないことを選択できます。
ネットワークエラーの計画
操作が無期限にハングし、アプリケーションが新しい操作を実行する際にブロックされる場合は、エラーを返すことが推奨されます。 maxTimeMSメソッドを使用して、個々の操作に時間制限を設定でき、その時間制限を超えた場合にアプリケーションが処理するエラーを返します。
各操作に設定する時間制限は、その操作のコンテキストによって異なります。
例
アプリケーションがinventoryコレクションから簡単な製品情報を読み取って表示する場合、これらの読み取り操作にかかる時間は 1 時間のみであることがかなり確実です。 クエリの実行時間が異常に長い場合は、ネットワークの問題が永続していることを示す適切なインジケーターです。 この操作でmaxTimeMSを 5000、つまり 5 秒に設定すると、アプリケーションはネットワークの問題があることを確認するとすぐにフィードバックを受け取ることを意味します。
フェイルオーバーのテスト
マテリアライズドテスト の一環として、Atlas は定期的なメンテナンスや特定の構成変更のために、レプリカセットの選挙を自動的に実行します。
アプリケーションがレプリカセットの選挙に対して回復力があるかどうかを確認するには、フェイルオーバー イベントをシミュレートしてフェイルオーバー プロセスをテストします。
回復力のあるサンプルアプリケーション
サンプルアプリケーションには、ネットワーク停止やフェイルオーバー イベントに対する回復力を確保するために、次の推奨事項をまとめています。
Atlas が提供する接続文字列を、再試行可能な書き込み、過半数の書込み保証(write concern)、デフォルトの読み取り保証(read concern)とともに使用します。
Specify an operation time limit with the maxTimeMS method. For instructions on how to set
maxTimeMS, refer to your specific Driver Documentation.重複キーとタイムアウトのエラーを処理します。
The application is an HTTP API that allows clients to create or list user records. It exposes an endpoint that accepts GET and POST requests http://localhost:3000:
方式 | エンドポイント | 説明 |
|---|---|---|
|
|
|
|
| リクエスト本文に |
1 // File: App.java 2 3 import java.util.Map; 4 import java.util.logging.Logger; 5 6 import org.bson.Document; 7 import org.json.JSONArray; 8 9 import com.mongodb.MongoException; 10 import com.mongodb.client.MongoClient; 11 import com.mongodb.client.MongoClients; 12 import com.mongodb.client.MongoCollection; 13 import com.mongodb.client.MongoDatabase; 14 15 import fi.iki.elonen.NanoHTTPD; 16 17 public class App extends NanoHTTPD { 18 private static final Logger LOGGER = Logger.getLogger(App.class.getName()); 19 20 static int port = 3000; 21 static MongoClient client = null; 22 23 public App() throws Exception { 24 super(port); 25 26 // Replace the uri string with your MongoDB deployment's connection string 27 String uri = "<atlas-connection-string>"; 28 client = MongoClients.create(uri); 29 30 start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); 31 LOGGER.info("\nStarted the server: http://localhost:" + port + "/ \n"); 32 } 33 34 public static void main(String[] args) { 35 try { 36 new App(); 37 } catch (Exception e) { 38 LOGGER.severe("Couldn't start server:\n" + e); 39 } 40 } 41 42 43 public Response serve(IHTTPSession session) { 44 StringBuilder msg = new StringBuilder(); 45 Map<String, String> params = session.getParms(); 46 47 Method reqMethod = session.getMethod(); 48 String uri = session.getUri(); 49 50 if (Method.GET == reqMethod) { 51 if (uri.equals("/")) { 52 msg.append("Welcome to my API!"); 53 } else if (uri.equals("/users")) { 54 msg.append(listUsers(client)); 55 } else { 56 msg.append("Unrecognized URI: ").append(uri); 57 } 58 } else if (Method.POST == reqMethod) { 59 try { 60 String name = params.get("name"); 61 if (name == null) { 62 throw new Exception("Unable to process POST request: 'name' parameter required"); 63 } else { 64 insertUser(client, name); 65 msg.append("User successfully added!"); 66 } 67 } catch (Exception e) { 68 msg.append(e); 69 } 70 } 71 72 return newFixedLengthResponse(msg.toString()); 73 } 74 75 static String listUsers(MongoClient client) { 76 MongoDatabase database = client.getDatabase("test"); 77 MongoCollection<Document> collection = database.getCollection("users"); 78 79 final JSONArray jsonResults = new JSONArray(); 80 collection.find().forEach((result) -> jsonResults.put(result.toJson())); 81 82 return jsonResults.toString(); 83 } 84 85 static String insertUser(MongoClient client, String name) throws MongoException { 86 MongoDatabase database = client.getDatabase("test"); 87 MongoCollection<Document> collection = database.getCollection("users"); 88 89 collection.insertOne(new Document().append("name", name)); 90 return "Successfully inserted user: " + name; 91 } 92 }
注意
次のサーバーアプリケーションではExpressが使用されています。これは実行前にプロジェクトに 依存関係 として追加する必要があります。
1 const express = require('express'); 2 const bodyParser = require('body-parser'); 3 4 // Use the latest client libraries by installing & importing them 5 const MongoClient = require('mongodb').MongoClient; 6 7 const app = express(); 8 app.use(bodyParser.json()); 9 app.use(bodyParser.urlencoded({ extended: true })); 10 11 const uri = "mongodb+srv://<db_username>:<db_password>@cluster0-111xx.mongodb.net/test?retryWrites=true&w=majority"; 12 13 const client = new MongoClient(uri); 14 15 // ----- API routes ----- // 16 app.get('/', (req, res) => res.send('Welcome to my API!')); 17 18 app.get('/users', (req, res) => { 19 const collection = client.db("test").collection("users"); 20 21 collection 22 .find({}) 23 .maxTimeMS(5000) 24 .toArray((err, data) => { 25 if (err) { 26 res.send("The request has timed out. Please check your connection and try again."); 27 } 28 return res.json(data); 29 }); 30 }); 31 32 app.post('/users', (req, res) => { 33 const collection = client.db("test").collection("users"); 34 collection.insertOne({ name: req.body.name }) 35 .then(result => { 36 res.send("User successfully added!"); 37 }, err => { 38 res.send("An application error has occurred. Please try again."); 39 }) 40 }); 41 // ----- End of API routes ----- // 42 43 app.listen(3000, () => { 44 console.log(`Listening on port 3000.`); 45 client.connect(err => { 46 if (err) { 47 console.log("Not connected: ", err); 48 process.exit(0); 49 } 50 console.log('Connected.'); 51 }); 52 });
注意
次の WebアプリケーションはFastAPI を使用します。新しいアプリケーションを作成するには、FastAPIサンプルファイル構造を使用します。
1 # File: main.py 2 3 from fastapi import FastAPI, Body, Request, Response, HTTPException, status 4 from fastapi.encoders import jsonable_encoder 5 6 from typing import List 7 from models import User 8 9 import pymongo 10 from pymongo import MongoClient 11 from pymongo import errors 12 13 # Replace the uri string with your |service| connection string 14 uri = "<atlas-connection-string>" 15 db = "test" 16 17 app = FastAPI() 18 19 20 def startup_db_client(): 21 app.mongodb_client = MongoClient(uri) 22 app.database = app.mongodb_client[db] 23 24 25 def shutdown_db_client(): 26 app.mongodb_client.close() 27 28 ##### API ROUTES ##### 29 30 def list_users(request: Request): 31 try: 32 users = list(request.app.database["users"].find().max_time_ms(5000)) 33 return users 34 except pymongo.errors.ExecutionTimeout: 35 raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="The request has timed out. Please check your connection and try again.") 36 37 38 def new_user(request: Request, user: User = Body(...)): 39 user = jsonable_encoder(user) 40 try: 41 new_user = request.app.database["users"].insert_one(user) 42 return {"message":"User successfully added!"} 43 except pymongo.errors.DuplicateKeyError: 44 raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Could not create user due to existing '_id' value in the collection. Try again with a different '_id' value.")