AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。

1 つのアプリケーションでの複数の接続

ほとんどのアプリケーションは単一のMongoDB接続を使用します。ただし、一部のアプリケーションでは、データ、パフォーマンスの最適化、またはアーキテクチャ要件のために複数の接続を分離することでメリットをもたらすことができます。

このチュートリアルでは、単一のNode.jsアプリケーション内で複数のMongoDB接続を確立する方法を学習します。

複数のMongoDB接続は、データの分離、パフォーマンスの向上、またはアーキテクチャの柔軟性を必要とするアプリケーションに役立ちます。

複数のMongoDB接続の一般的なユースケースには、次のようなものがあります。

  • マルチテナント アプリケーション : 各テナントは、データ分離とセキュリティのために、独自の接続を持つ個別のデータベースを使用

  • マイクロサービス アーキテクチャ : 各サービスは専用のデータベース接続を維持

  • 負荷分散 : 読み取りおよび書込み操作を複数のデータベースインスタンスにわたって分散する

  • データ処理 : 分析またはレポート作成のために複数のMongoDBサーバーから同時にデータを取得

異なるテナントまたはカスタマーが同じ Webアプリケーションを共有しているものの、個別に分離されたデータベースが必要なマルチテナントアプリケーションを検討します。このシナリオでは、各テナントが専用のMongoDB接続を持つことができます。これにより、すべてが同じアプリケーション内で動作しながら、各テナントのデータ分離、セキュリティ、カスタマイズが確保されます。このアプローチにより管理が簡素化され、既存のテナントに影響を与えずに新しいテナントがプラットフォームに参加する際に増やすする方法が提供されます。

アプリケーションに複数の接続を実装する方法を検討する際には、次のMongoDB の概念を考慮します。

これらの概念は、効率的なデータ管理とパフォーマンスの最適化に複数のMongoDB接続が必要なシナリオで役割を果たします。

このチュートリアルでは、次のアクションを実行します。

  • 環境を設定し、必要な依存関係をインストールします

  • MongoDB に接続する

  • プライマリMongoDB接続のセットアップ

  • MongoDBのセカンダリ接続を設定する

  • 既存のスキーマを使用する

  • スキーマの柔軟性の設定

  • 同じ接続内のデータベースを切り替える

このチュートリアルを開始する前に、MongoDB Atlasクラスターが必要です。無料のMongoDB Atlasクラスターを作成する方法については、MongoDB学ぶチュートリアルを参照してください。

注意

このチュートリアルでは、 MongoDB Server 8.0.12 とNode.jsバージョン 20.15.1 を使用します。

1

プロジェクトに新しいディレクトリを作成し、新しいNode.jsプロジェクトを初期化します。

mkdir mongodb-multiple-connectionscd mongodb-multiple-connectionsnpm init -y
2

このチュートリアルに必要な依存関係をインストールします。

npm install express mongoose

このチュートリアルでは、WebフレームワークにはExpress .js を使用し、 MongoDBオブジェクトモデリングにはMongoose を使用します。

注意

このチュートリアルでは、 MongoDB .の一般的な オブジェクト フィールド モデリング(ODM)ライブラリであるMongoose を使用します。 Mongooseを使い始める方法の詳細については、 「 Mongooseを使い始める 」チュートリアルを参照してください。

3

MongoDB接続文字列を保存するには、プロジェクトルートディレクトリに .envファイルを作成します。

touch .env

次の環境変数を .envファイルに追加します。

PRIMARY_CONN_STR=<your-primary-connection-string>SECONDARY_CONN_STR=<your-secondary-connection-string>

プレースホルダー値を実際のMongoDB Atlas接続文字列に置き換えます。MongoDB Atlas接続文字列を見つける方法については、クラスターへの接続チュートリアルを参照してください。

環境変数を読み込むには、dotenvパッケージをインストールします。

npm install dotenv

これで、アプリケーション内に複数のMongoDB接続を設定する準備ができたプロジェクトが あります 。

このチュートリアルを完了すると、このアプリケーションのプロジェクトディレクトリは次の構造になります。

mongodb-multiple-connections/├── .env # Environment variables├── package.json # Project dependencies├── package-lock.json # Dependency lock file├── node_modules/ # Installed packages├── index.js # Main application file├── db.primary.js # Primary connection configuration├── db.secondary.js # Secondary connection configuration└── product.schema.js # Product schema definition

このチュートリアルで作成するキー ファイルは、次の目的で使用されます。

  • インデックス.js :両方の接続を使用するメインのアプリケーションファイル

  • db.primary.js :mongoose.connect() を使用してプライマリMongoDB接続を構成します

  • db.secondary.js :mongoose.createConnection() を使用してセカンダリMongoDB接続を構成します

  • 製品。スキーマ.js :両方の接続の再利用可能な製品スキーマを定義します

  • .env : MongoDB接続文字列を安全に保存します

このセクションでは、 Mongooseを使用して、アプリケーション内でプライマリMongoDB接続を設定する方法を学習します。mongoose.connect()メソッドを使用して、アプリケーションのプライマリMongoDBデータベース接続を確立します。このメソッドは、アプリケーション全体に対して単一の接続プールを管理します。

1

db.primary.js という名前の新しいファイルで、メインのアプリケーションファイルで使用する接続メソッドとして、index.js を定義します。このメソッドはMongoDB接続を構成し、イベントを処理します。次のコードをコピーして、db.primary.jsファイルに貼り付けます。

require('dotenv').config();const mongoose = require("mongoose"); module.exports = async (uri, options = {}) => { // By default, Mongoose skips properties not defined in the schema (strictQuery). // You can adjust it based on your configuration. mongoose.set('strictQuery', true); // Connect to MongoDB try { await mongoose.connect(uri, options); console.info("MongoDB primary connection initiated"); } catch (err) { console.error("MongoDB primary connection failed, " + err); } // Event handling mongoose.connection.once('open', () => console.info("MongoDB primary connection opened!")); mongoose.connection.on('connected', () => console.info("MongoDB primary connection succeeded!")); mongoose.connection.on('error', (err) => { console.error("MongoDB primary connection failed, " + err); mongoose.disconnect(); }); mongoose.connection.on('disconnected', () => console.info("MongoDB primary connection disconnected!")); // Graceful exit process.on('SIGINT', async () => { try { await mongoose.connection.close(); console.info("Mongoose primary connection disconnected through app termination!"); process.exit(0); } catch (err) { console.error("Error during graceful shutdown:", err); process.exit(1); } });}
2

アプリケーションで操作を実行するためのスキーマを作成します。次のコードに示すように、product.schema.js という名前の別のファイルにスキーマを書き込み、エクスポートします。

const mongoose = require("mongoose"); module.exports = (options = {}) => { // Schema for Product return new mongoose.Schema( { store: { _id: mongoose.Types.ObjectId, // Reference-id to the store collection name: String }, name: String, price: Number, category: String, description: String // add required properties }, options );}
3

メインの index.jsファイルに db.primary.jsファイルをインポートし、ここで定義されているメソッドを使用してMongoDB のプライマリ接続を確立します。必要に応じて、オプションの接続オプションオブジェクトを渡すこともできます。

次に、product.schema.jsファイルをインポートして、製品スキーマにアクセスします。これにより、モデルを作成し、アプリケーション内の製品に関連する操作を実行できます。次のコードをコピーして、index.jsファイルに貼り付け、プライマリ接続を設定し、サンプル製品データに対して操作を実行します。

// Load environment variablesrequire('dotenv').config();const mongoose = require("mongoose"); // Async function to establish the primary MongoDB connectionasync function establishPrimaryConnection() { try { await require("./db.primary.js")(process.env.PRIMARY_CONN_STR, { // (optional) connection options }); } catch (error) { console.error('Failed to establish primary connection:', error); process.exit(1); }} // Initialize connectionestablishPrimaryConnection(); // Import Product Schemaconst productSchema = require("./product.schema.js")({ collection: "products", // Pass configuration options if needed}); // Create Modelconst ProductModel = mongoose.model("Product", productSchema); // Sample products dataconst sampleProducts = [ { name: "Laptop Pro", price: 1299.99, category: "Electronics", description: "High-performance laptop for professionals" }, { name: "Wireless Headphones", price: 199.99, category: "Electronics", description: "Premium noise-cancelling headphones" }, { name: "Coffee Maker", price: 89.99, category: "Kitchen", description: "Automatic drip coffee maker" }]; // Wait for connection to be ready before executing operationsmongoose.connection.once('open', async () => { console.log('Primary database connected, executing operations...'); try { // Check if products already exist const existingCount = await ProductModel.countDocuments(); console.log(`Existing products in primary DB: ${existingCount}`); if (existingCount === 0) { console.log('Inserting sample products into primary database...'); await ProductModel.insertMany(sampleProducts); console.log('Sample products inserted into primary database!'); } // Find and display a product let product = await ProductModel.findOne(); console.log('Product found in primary DB:', product); // Display all products const allProducts = await ProductModel.find(); console.log(`Total products in primary DB: ${allProducts.length}`); } catch (error) { console.error('Error with primary database operations:', error); }});

アプリケーションに複数のMongoDB接続が必要な場合。

MongoDB のセカンダリ接続は、さまざまなユースケースで構成できます。このセクションでは、セカンダリ接続の設定方法と使用方法を説明します。

1

mongoose.createConnection() メソッドを使用して、 ファイルに接続コードを作成しますdb.secondary.js使用して複数のドキュメントを挿入できます。この方法では、プライマリMongoDB接続に以前使用した mongoose.connect() メソッドとは異なり、特定のユースケースやデータアクセスパターンに合わせてそれぞれがカスタマイズされた個別の接続プールを確立できます。

const mongoose = require("mongoose"); module.exports = (uri, options = {}) => { // Connect to MongoDB const db = mongoose.createConnection(uri, options); // By default, Mongoose skips properties not defined in the schema (strictQuery). // Adjust it based on your configuration. db.set('strictQuery', true); // Event handling db.once('open', () => console.info("MongoDB secondary connection opened!")); db.on('connected', () => console.info(`MongoDB secondary connection succeeded!`)); db.on('error', (err) => { console.error(`MongoDB secondary connection failed, ` + err); db.close(); }); db.on('disconnected', () => console.info(`MongoDB secondary connection disconnected!`)); // Graceful exit process.on('SIGINT', async () => { try { await db.close(); console.info(`Mongoose secondary connection disconnected through app termination!`); process.exit(0); } catch (err) { console.error("Error during graceful shutdown:", err); process.exit(1); } }); // Export db object return db;}
2

メインの index.jsファイルに db.secondary.jsファイルをインポートし、db という名前の変数を使用して接続オブジェクトを作成し、ここで定義されているメソッドを使用してセカンダリMongoDB接続を確立します。必要に応じて、オプションの接続オプションオブジェクトを渡すこともできます。次のコードを index.jsファイルの末尾に追加します。

// Load environment variablesrequire('dotenv').config(); // Establish the secondary MongoDB connectionconst db = require("./db.secondary.js")(process.env.SECONDARY_CONN_STR, { // (optional) connection options}); // Import Product Schemaconst SecondaryProductSchema = require("./product.schema.js")({ collection: "products", // Pass configuration options if needed}); // Create Model using the secondary connectionconst SecondaryProductModel = db.model("Product", SecondaryProductSchema); // Sample products data for secondary databaseconst SecondarySampleProducts = [ { name: "Smart Watch", price: 199.99, category: "Electronics", description: "Advanced fitness tracking smartwatch" }, { name: "Bluetooth Speaker", price: 79.99, category: "Electronics", description: "Portable wireless speaker with premium sound" }, { name: "Desk Lamp", price: 49.99, category: "Home", description: "LED desk lamp with adjustable brightness" }]; // Wait for secondary connection to be ready before executing operationsdb.once('open', async () => { console.log('Secondary database connected, executing operations...'); try { // Check if products already exist const existingCount = await SecondaryProductModel.countDocuments(); console.log(`Existing products in secondary DB: ${existingCount}`); if (existingCount === 0) { console.log('Inserting sample products into secondary database...'); await SecondaryProductModel.insertMany(SecondarySampleProducts); console.log('Sample products inserted into secondary database!'); } // Find and display a product let product = await SecondaryProductModel.findOne(); console.log('Product found in secondary DB:', product); // Display all products const allProducts = await SecondaryProductModel.find(); console.log(`Total products in secondary DB: ${allProducts.length}`); } catch (error) { console.error('Error with secondary database operations:', error); }});

接続を設定したら、新しい dbオブジェクトを使用してモデルを作成できます。次のセクションでは、特定のデータアクセスと管理のニーズに最も適した設定を選択するために、さまざまなシナリオと例を紹介します。

両方の接続が同じデータモデルで動作する場合は、プライマリ接続で使用されていたのと同じ product.schema.jsファイルを使用します。

製品スキーマにアクセスするには、product.schema.jsファイルをインポートします。これにより、dbオブジェクトを使用してモデルを作成し、アプリケーション内の製品に関連する操作を実行できます。

// Import Product Schemaconst secondaryProductSchema = require("./product.schema.js")({ collection: "products", // Pass configuration options if needed}); // Create Modelconst SecondaryProductModel = db.model("Product", secondaryProductSchema); // Wait for secondary connection to be ready before executing operationsdb.once('open', async () => { console.log('Secondary database connected, executing operations...'); try { // Check if products already exist in secondary database const existingCount = await SecondaryProductModel.countDocuments(); console.log(`Existing products in secondary DB: ${existingCount}`); if (existingCount === 0) { console.log('Inserting sample products into secondary database...'); await SecondaryProductModel.insertMany(sampleProducts); console.log('Sample products inserted into secondary database!'); } // Find and display a product let product = await SecondaryProductModel.findOne(); console.log('Product found in secondary DB:', product); // Display all products const allProducts = await SecondaryProductModel.find(); console.log(`Total products in secondary DB: ${allProducts.length}`); } catch (error) { console.error('Error with secondary database operations:', error); }});

複数のMongoDB接続を扱う場合、特定のユースケースに基づいてスキーマを調整する柔軟性が重要です。プライマリ接続ではデータの整合性を確保するために検証を持つ厳格なスキーマが必要になる場合がありますが、セカンダリ接続が別の目的で提供されるシナリオもあります。インスタンスの場合、セカンダリ接続では アーカイブサーバーに分析用データが保存される場合があり、過去のユースケースによってスキーマ要件が異なります。このセクションでは、セカンダリ接続のスキーマの柔軟性を構成し、アプリケーションの個別のニーズ を満たできるようにする方法について説明します。

Mongooseでスキーマの柔軟性を維持したい場合は、セカンダリ接続用にスキーマを構成するときにスキーマオプション で strict: falseプロパティを渡します。これにより、スキーマに厳密に準拠しないデータを処理できます。

製品スキーマにアクセスするには、product.schema.jsファイルをインポートします。これにより、dbオブジェクトを使用してモデルを作成し、アプリケーション内の製品に関連する操作を実行できます。

// Import Product Schemaconst secondaryProductSchema = require("./product.schema.js")({ collection: "products", strict: false // Pass configuration options if needed}); // Create Modelconst SecondaryProductModel = db.model("Product", secondaryProductSchema); // Wait for secondary connection to be ready before executing operationsdb.once('open', async () => { console.log('Secondary database (flexible schema) connected, executing operations...'); try { // Check if products already exist in secondary database const existingCount = await SecondaryProductModel.countDocuments(); console.log(`Existing products in secondary DB: ${existingCount}`); if (existingCount === 0) { // Add extra fields to demonstrate schema flexibility const flexibleSampleProducts = sampleProducts.map(product => ({ ...product, extraField: "This field is not in the schema but will be saved due to strict: false", timestamp: new Date() })); console.log('Inserting sample products with extra fields into secondary database...'); await SecondaryProductModel.insertMany(flexibleSampleProducts); console.log('Sample products with extra fields inserted into secondary database!'); } // Find and display a product let product = await SecondaryProductModel.findOne(); console.log('Product found in secondary DB (flexible schema):', product); // Display all products const allProducts = await SecondaryProductModel.find(); console.log(`Total products in secondary DB: ${allProducts.length}`); } catch (error) { console.error('Error with secondary database operations:', error); }});

アプリケーションのデータベース設定内で、db.useDb() メソッドを使用して、異なるデータベースを切り替えることができます。このメソッドを使用すると、同じ接続プールを共有しながら、特定のデータベースに関連付けられた新しい接続オブジェクトを作成できます。

このアプローチでは、各データベースの個別のデータコンテキストを維持しつつ、単一の接続を使用して、アプリケーション内の複数のデータベースを管理できます。

製品スキーマにアクセスするには、product.schema.jsファイルをインポートします。これにより、dbオブジェクトを使用してモデルを作成し、アプリケーション内の製品に関連する操作を実行できます。

複数の店舗が独立して動作し、各店舗が製品管理用に独自のデータベースを維持するeコマースプラットフォームを検討してください。次の例に示すように、 共有接続プールを維持しつつ異なるストアデータベースを切り替えるには、db.useDb() メソッドを使用します。

// Load environment variablesrequire('dotenv').config(); // Establish the secondary MongoDB connectionconst db = require("./db.secondary.js")(process.env.SECONDARY_CONN_STR, { // (optional) connection options}); // Import Product Schemaconst secondaryProductSchema = require("./product.schema.js")({ collection: "products", // strict: false // that doesn't adhere strictly to the schema! // Pass configuration options if needed}); // Base sample products dataconst sampleProducts = [ { name: "Laptop Pro", price: 1299.99, category: "Electronics", description: "High-performance laptop for professionals" }, { name: "Wireless Headphones", price: 199.99, category: "Electronics", description: "Premium noise-cancelling headphones" }, { name: "Coffee Maker", price: 89.99, category: "Kitchen", description: "Automatic drip coffee maker" }]; // Sample store-specific productsconst storeAProducts = sampleProducts.map(product => ({ ...product, store: { name: "Store A" }, storeId: "A"})); const storeBProducts = [ { name: "Gaming Chair", price: 299.99, category: "Furniture", description: "Ergonomic gaming chair with RGB lighting", store: { name: "Store B" }, storeId: "B" }, { name: "Mechanical Keyboard", price: 149.99, category: "Electronics", description: "RGB mechanical gaming keyboard", store: { name: "Store B" }, storeId: "B" }]; // Create a connection for 'Store A'const storeA = db.useDb('StoreA'); // Create Modelconst SecondaryStoreAProductModel = storeA.model("Product", secondaryProductSchema); // Wait for Store A connection to be readystoreA.once('open', async () => { console.log('Store A database connected, executing operations...'); try { // Check if products already exist in Store A const existingCount = await SecondaryStoreAProductModel.countDocuments(); console.log(`Existing products in Store A: ${existingCount}`); if (existingCount === 0) { console.log('Inserting sample products into Store A database...'); await SecondaryStoreAProductModel.insertMany(storeAProducts); console.log('Sample products inserted into Store A database!'); } // Find and display a product let product = await SecondaryStoreAProductModel.findOne(); console.log('Product found in Store A:', product); // Display all products const allProducts = await SecondaryStoreAProductModel.find(); console.log(`Total products in Store A: ${allProducts.length}`); } catch (error) { console.error('Error with Store A operations:', error); }}); // Create a connection for 'Store B'const storeB = db.useDb('StoreB'); // Create Modelconst SecondaryStoreBProductModel = storeB.model("Product", secondaryProductSchema); // Wait for Store B connection to be readystoreB.once('open', async () => { console.log('Store B database connected, executing operations...'); try { // Check if products already exist in Store B const existingCount = await SecondaryStoreBProductModel.countDocuments(); console.log(`Existing products in Store B: ${existingCount}`); if (existingCount === 0) { console.log('Inserting sample products into Store B database...'); await SecondaryStoreBProductModel.insertMany(storeBProducts); console.log('Sample products inserted into Store B database!'); } // Find and display a product let product = await SecondaryStoreBProductModel.findOne(); console.log('Product found in Store B:', product); // Display all products const allProducts = await SecondaryStoreBProductModel.find(); console.log(`Total products in Store B: ${allProducts.length}`); } catch (error) { console.error('Error with Store B operations:', error); }});

上記の例では、Store A と Store B の個別のデータベース接続を確立しており、各店舗には独自の製品データが含まれています。このアプローチでは、データを分離すると同時に、効率的なリソース管理のために単一の共有接続プールを利用します。

上記の静的アプローチでは、事前定義された名前を持つ各店舗の明示的な接続が作成されます(StoreA、StoreB)。

動的店舗管理には、店舗識別子を パラメーターとして受け入れ、 接続オブジェクトを返す関数を作成します。この機能により、識別子によるストアの切り替えが可能になり、既存の接続を再利用して効率を向上させます。

// Function to get connection object for particular store's databasefunction getStoreConnection(storeId) { return db.useDb("Store"+storeId, { useCache: true });} // Create a connection for 'Store A'const store = getStoreConnection("A"); // Create Modelconst SecondaryStoreProductModel = store.model("Product", secondaryProductSchema); // Wait for store connection to be readystore.once('open', async () => { console.log('Store A (dynamic) database connected, executing operations...'); try { // Check if products already exist in the store const existingCount = await SecondaryStoreProductModel.countDocuments(); console.log(`Existing products in Store A (dynamic): ${existingCount}`); if (existingCount === 0) { // Use the same store A products from the previous example console.log('Inserting sample products into Store A (dynamic) database...'); await SecondaryStoreProductModel.insertMany(storeAProducts); console.log('Sample products inserted into Store A (dynamic) database!'); } // Find and display a product let product = await SecondaryStoreProductModel.findOne(); console.log('Product found in Store A (dynamic):', product); // Display all products const allProducts = await SecondaryStoreProductModel.find(); console.log(`Total products in Store A (dynamic): ${allProducts.length}`); } catch (error) { console.error('Error with Store A (dynamic) operations:', error); }});

動的アプローチでは、必要に応じて接続インスタンスが作成されキャッシュされるため、各ストアへの個別の接続を手動で管理する必要がなくなります。このアプローチにより、アプリケーション内の複数のストアを操作する必要があるシナリオでの柔軟性とリソースの効率が向上します。

このチュートリアルでは、 Mongooseを使用してNode.jsアプリケーションに複数のMongoDB接続を実装する方法を説明します。プライマリ接続とセカンダリ接続の確立、スキーマの柔軟性の実装、単一の接続プール内で複数のデータベースの管理方法を学習しました。

これらの手法により、複数のデータコンテキストを必要とするアプリケーションのデータ分離、パフォーマンスの向上、アーキテクチャの柔軟性が向上します。特定のアプリケーション要件を満たす接続戦略を実装できるようになりました。複数のMongoDB接続を引き続き操作する場合は、次のベストプラクティスと追加リソースを考慮してください。

Node.jsアプリケーションに複数のMongoDB接続を実装する場合は、次のベストプラクティスに従います。

  • 接続プーリング:接続プーリングを使用して、 MongoDB接続を効率的に管理します。接続プーリングにより、接続の再利用が可能になり、オーバーヘッドが削減されます。詳細については、サーバー マニュアルの 接続Pooling および MongoDB Node.jsドライバー ドキュメントの 接続プールを使用した接続の管理 を参照してください。

  • エラー処理 : 接続の信頼性を確保するために、適切なエラー処理、ログ、および回復メカニズムを実装します。

  • セキュリティ: 機密データを取り扱う際は、認証、承認、およびセキュアな通信の実行を実装します。詳細については、「認証メカニズム」を参照してください。

  • スケーラビリティ : 水平と垂直の両方のスケーリング要件をサポートするように接続戦略を設計します。

  • テスト :フェイルオーバーシナリオ、高負荷、リソース制約などのさまざまな条件で複数の接続セットアップをテストします。

Mongooseを使い始める方法の詳細については、 「 Mongooseを使い始める 」チュートリアルの「 サードパーティ統合 」セクションを参照してください。

MongoDBでMongooseを使用する方法の詳細については、Mongoose のドキュメント を参照してください。