Mongoose dan beberapa database dalam satu proyek node.js

123

Saya melakukan proyek Node.js yang berisi sub proyek. Satu sub proyek akan memiliki satu database Mongodb dan Mongoose akan digunakan untuk membungkus dan menanyakan db. Tapi masalahnya adalah

  • Mongoose tidak mengizinkan untuk menggunakan banyak database dalam satu instance luwak karena modelnya dibangun di satu koneksi.
  • Untuk menggunakan beberapa instance luwak, Node.js tidak mengizinkan beberapa instance modul karena memiliki sistem cache require(). Saya tahu menonaktifkan caching modul di Node.js tetapi saya pikir ini bukan solusi yang baik karena hanya perlu untuk luwak.

    Saya sudah mencoba menggunakan createConnection()dan openSet()di luwak, tapi itu bukan solusinya.

    Saya telah mencoba untuk menyalin contoh luwak ( http://blog.imaginea.com/deep-copy-in-javascript/ ) untuk meneruskan contoh luwak baru ke sub proyek, tetapi itu melempar RangeError: Maximum call stack size exceeded.

Saya ingin tahu apakah ada cara untuk menggunakan banyak database dengan luwak atau solusi apa pun untuk masalah ini? Karena menurut saya luwak cukup mudah dan cepat. Atau modul lain sebagai rekomendasi?

pupot
sumber

Jawaban:

38

Satu hal yang dapat Anda lakukan adalah, Anda mungkin memiliki subfolder untuk setiap proyek. Jadi, instal luwak di subfolder itu dan memerlukan () mongoose dari foldernya sendiri di setiap sub aplikasi. Bukan dari akar proyek atau dari global. Jadi satu sub proyek, satu instalasi luwak dan satu contoh luwak.

-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/

Di foo_db_connect.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;

Di bar_db_connect.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;

Dalam file db_access.js

var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app

Sekarang, Anda dapat mengakses banyak database dengan luwak.

yemaw
sumber
2
Artinya, setiap proyek akan memiliki koneksi sendiri-sendiri. Anda tidak akan dapat mengelola 100k koneksi. Saya pikir akan lebih baik menggunakan useDbperintah yang menggunakan kumpulan koneksi yang sama.
xpepermint
1
xpepermint apakah Anda dapat menunjukkan contoh untuk useDb - Saya mengalami masalah ini saat ini stackoverflow.com/questions/37583198/…
Lion789
4
Ini terlihat seperti beban besar pada proyek. bukankah begitu?
Eshwar Prasad Yaddanapudi
1
Memiliki beberapa contoh koneksi yang berbeda (misalnya untuk DB Pengguna, DB Sesi, dan untuk data aplikasi) per aplikasi tidak masalah. Ini bukan 'beban besar' atau akan menyebabkan masalah penskalaan dan merupakan kasus penggunaan umum.
Iain Collins
Kamu adalah yang terbaik temanku! Terima kasih banyak! itu berhasil untuk saya! Terima kasih!
Biruel Rick
214

Menurut manual halus , createConnection() dapat digunakan untuk menghubungkan ke beberapa database.

Namun, Anda perlu membuat model terpisah untuk setiap koneksi / database:

var conn      = mongoose.createConnection('mongodb://localhost/testA');
var conn2     = mongoose.createConnection('mongodb://localhost/testB');

// stored in 'testA' database
var ModelA    = conn.model('Model', new mongoose.Schema({
  title : { type : String, default : 'model in testA database' }
}));

// stored in 'testB' database
var ModelB    = conn2.model('Model', new mongoose.Schema({
  title : { type : String, default : 'model in testB database' }
}));

Saya cukup yakin Anda dapat membagikan skema di antara mereka, tetapi Anda harus memeriksa untuk memastikannya.

robertklep
sumber
4
Ya, koneksi bernama dan skema bersama adalah cara yang harus dilakukan. Setiap koneksi akan membutuhkan model unik sesuai contoh Robert.
Simon Holmes
21
Juga checkout useDb()tersedia dalam 3.8 untuk berbagi kumpulan koneksi yang mendasarinya: github.com/LearnBoost/mongoose/wiki/…
aaronheckmann
1
Misalkan saya memiliki database yang dibuat secara otomatis (Katakanlah n jumlah database). Tidak satu atau dua. Apakah ada cara untuk menghubungkannya tanpa membuat model terpisah untuk setiap database?
Anooj Krishnan G
1
@AnoojKrishnanG Saya rasa itu tidak mungkin, tidak. Anda perlu membuat model terhadap setiap database secara terpisah. Namun, seperti yang sudah saya nyatakan dalam jawaban saya, Anda mungkin dapat membagikan skema di antara koneksi, yang dapat menghemat waktu pengkodean.
robertklep
1
Anda dapat berbagi skema di berbagai model, dan karena itu DB. var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
memberikan
42

Cukup terlambat tetapi ini mungkin membantu seseorang. Jawaban saat ini mengasumsikan Anda menggunakan file yang sama untuk koneksi dan model Anda.

Dalam kehidupan nyata, ada kemungkinan besar Anda memecah model Anda menjadi file yang berbeda. Anda dapat menggunakan sesuatu seperti ini di file utama Anda:

mongoose.connect('mongodb://localhost/default');

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log('connected');
});

seperti yang dijelaskan di dokumen. Dan kemudian di file model Anda, lakukan sesuatu seperti berikut:

import mongoose, { Schema } from 'mongoose';

const userInfoSchema = new Schema({
  createdAt: {
    type: Date,
    required: true,
    default: new Date(),
  },
  // ...other fields
});

const myDB = mongoose.connection.useDb('myDB');

const UserInfo = myDB.model('userInfo', userInfoSchema);

export default UserInfo;

Dimana myDB adalah nama database Anda.

Tahnik Mustasin
sumber
Terima kasih - Saya dapat menggunakan 3 database berbeda dalam satu aplikasi menggunakan: const mongoose = require ('mongoose'); Const Schema = mongoose.Schema; const mySchema = Skema baru ({}); const mydbvar = mongoose.connection.useDb ('mydb') module.exports = mydbvar.model ('myCollection', MySchema);
Johnathan Enslin
2
Jelas contoh terbaik dan paling dunia nyata. Hubungkan ke db default (seperti jika Anda menggunakan sesuatu seperti SQL Server) dan kemudian manfaatkan useDb untuk menargetkan DML Anda pada database yang sesuai. (Sangat membantu untuk menjaga pengguna Anda dalam satu db dan data Anda di yang lain.) Tidak perlu mulai membuat banyak koneksi ketika pada akhirnya Anda mengirim permintaan ke server yang sama. Sekarang, jika Anda terhubung ke dua server yang berbeda, itu adalah ketel ikan yang berbeda.
Newclique
2
Seperti yang dikatakan @Wade, sejauh yang saya mengerti, solusi ini hanya berfungsi ketika semua database berada di server yang sama. Tidak jelas apakah ini menjawab pertanyaan OP dan IMO agak menyesatkan.
joniba
Inilah yang saya butuhkan untuk migrasi MongoDB Atlas test, dan juga untuk menghindari memiliki banyak koneksi. Namun, saya juga .dbdi akhir ( const v1 = mongoose.connection.useDb('test').db) karena db lama tidak perlu dikelola luwak.
Polv
37

Sebagai pendekatan alternatif, Mongoose mengekspor konstruktor untuk instance baru pada instance default. Jadi hal seperti ini mungkin terjadi.

var Mongoose = require('mongoose').Mongoose;

var instance1 = new Mongoose();
instance1.connect('foo');

var instance2 = new Mongoose();
instance2.connect('bar');

Ini sangat berguna saat bekerja dengan sumber data terpisah, dan juga saat Anda ingin memiliki konteks database terpisah untuk setiap pengguna atau permintaan. Anda harus berhati-hati, karena memungkinkan untuk membuat BANYAK koneksi saat melakukan ini. Pastikan untuk memanggil disconnect () ketika instance tidak diperlukan, dan juga untuk membatasi ukuran kumpulan yang dibuat oleh setiap instance.

Eric
sumber
1
apakah ini cara lain untuk menulis 'Di Atas Jawaban' ?
pravin
11
Ini bukan jawaban di atas, lebih baik. Jawaban di atas menginstal banyak salinan Mongoose, jika tidak perlu.
Martín Valdés de León
bagaimana saya membuat kueri menggunakan metode ini?
shahidfoy
2
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
Abdallah Al Barmawi
Bahkan lebih baik bekerja dalam kasus saya karena saya memiliki kredensial yang sama sekali berbeda untuk setiap koneksi, apalagi model dan database.
tzn
0

Solusi yang sedikit dioptimalkan (bagi saya setidaknya). tulis ini ke file db.js dan minta ini ke mana pun diperlukan dan panggil dengan pemanggilan fungsi dan Anda siap melakukannya.

   const MongoClient = require('mongodb').MongoClient;
    async function getConnections(url,db){
        return new Promise((resolve,reject)=>{
            MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
                if(err) { console.error(err) 
                    resolve(false);
                }
                else{
                    resolve(client.db(db));
                }
            })
        });
    }

    module.exports = async function(){
        let dbs      = [];
        dbs['db1']     = await getConnections('mongodb://localhost:27017/','db1');
        dbs['db2']     = await getConnections('mongodb://localhost:27017/','db2');
        return dbs;
    };
PKInd007
sumber