Mongoose e database multipli in un singolo progetto node.js


123

Sto facendo un progetto Node.js che contiene sottoprogetti. Un sottoprogetto avrà un database Mongodb e Mongoose verrà utilizzato per il wrapping e l'interrogazione di db. Ma il problema è

  • Mongoose non consente di utilizzare più database in una singola istanza di mangusta poiché i modelli sono costruiti su una connessione.
  • Per utilizzare più istanze di mangusta, Node.js non consente più istanze di moduli poiché ha un sistema di memorizzazione nella cache in formato require(). So disabilitare la memorizzazione nella cache del modulo in Node.js ma penso che non sia la buona soluzione in quanto è necessaria solo la mangusta.

    Ho provato a usare createConnection()e openSet()in mangusta, ma non era la soluzione.

    Ho provato a copiare in profondità l'istanza di mongoose ( http://blog.imaginea.com/deep-copy-in-javascript/ ) per passare nuove istanze di mongoose al sottoprogetto, ma viene lanciato RangeError: Maximum call stack size exceeded.

Voglio sapere se esiste comunque l'utilizzo di più database con mangusta o qualsiasi soluzione alternativa per questo problema? Perché penso che la mangusta sia abbastanza facile e veloce. O altri moduli come raccomandazioni?

Risposte:


38

Una cosa che puoi fare è che potresti avere sottocartelle per ogni progetto. Quindi, installa mongoose in quelle sottocartelle e require () mongoose dalle proprie cartelle in ogni sotto-applicazione. Non dalla radice del progetto o da globale. Quindi un sottoprogetto, un'installazione di mangusta e un'istanza di mangusta.

-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/

In foo_db_connect.js

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

In bar_db_connect.js

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

Nei file db_access.js

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

Ora puoi accedere a più database con mongoose.


2
Ciò significa che ogni progetto avrà la sua connessione. Non sarai in grado di gestire 100k connessioni. Penso che sarebbe meglio usare il useDbcomando che utilizza lo stesso pool di connessioni.
xpepermint

1
xpepermint sei in grado di mostrare un esempio per useDb - Sto avendo questo problema attualmente stackoverflow.com/questions/37583198/...
Lion789

4
Questo sembra un enorme fardello per il progetto. non credi?
Eshwar Prasad Yaddanapudi

1
Avere poche istanze di connessione diverse (ad esempio per un DB utente, un DB di sessione e per i dati dell'applicazione) per applicazione va assolutamente bene. Non è "un peso enorme" o causerà problemi di ridimensionamento ed è un caso d'uso comune.
Iain Collins

Sei il migliore amico mio! grazie mille! per me funziona! Grazie!
Biruel Rick

214

Secondo il manuale fine , createConnection() può essere utilizzato per connettersi a più database.

Tuttavia, è necessario creare modelli separati per ogni connessione / 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' }
}));

Sono abbastanza sicuro che puoi condividere lo schema tra di loro, ma devi controllare per esserne sicuro.


4
Sì, le connessioni denominate e uno schema condiviso sono la strada da percorrere, penso. Ogni connessione avrà bisogno di un modello unico come da esempio di Robert.
Simon Holmes

21
useDb()Disponibile anche checkout in 3.8 per condividere il pool di connessioni sottostante: github.com/LearnBoost/mongoose/wiki/…
aaronheckmann

1
Supponiamo di avere un database generato automaticamente (Dire n numero di database). Non uno o due. C'è un modo per connettersi a questi senza creare un modello separato per ogni database?
Anooj Krishnan G

1
@AnoojKrishnanG Non credo sia possibile, no. È necessario creare il modello su ogni database separatamente. Tuttavia, come ho già affermato nella mia risposta, potresti essere in grado di condividere lo schema tra le connessioni, il che potrebbe far risparmiare un po 'di tempo di codifica.
robertklep

1
È possibile condividere lo schema tra i diversi modelli e quindi i DB. var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
concedere

42

Abbastanza tardi ma questo potrebbe aiutare qualcuno. Le risposte attuali presumono che tu stia utilizzando lo stesso file per le tue connessioni e modelli.

Nella vita reale, c'è un'alta probabilità che tu stia suddividendo i tuoi modelli in file diversi. Puoi usare qualcosa di simile nel tuo file principale:

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

const db = mongoose.connection;

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

che è proprio come è descritto nei documenti. E poi nei tuoi file di modello, fai qualcosa come quanto segue:

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;

Dove myDB è il nome del database.


Grazie - sono stato in grado di utilizzare 3 diversi database all'interno di una singola applicazione utilizzando: const mongoose = require ('mongoose'); const Schema = mongoose.Schema; const mySchema = new Schema ({}); const mydbvar = mongoose.connection.useDb ('mydb') module.exports = mydbvar.model ('myCollection', MySchema);
Johnathan Enslin,

2
Sicuramente l'esempio migliore e più reale. Connettiti al database predefinito (proprio come se stessi usando qualcosa come SQL Server) e poi approfitta di useDb per indirizzare il tuo DML al database appropriato. (Molto utile per mantenere gli utenti in un database e i dati in un altro.) Non è necessario iniziare a effettuare più connessioni quando alla fine si inviano richieste allo stesso server. Ora, se ti stavi connettendo a due server diversi, sarebbe una cosa diversa.
Newclique

2
Come ha detto @Wade, per quanto ho capito questa soluzione funziona solo quando tutti i database si trovano sullo stesso server. Non è chiaro se questo risponde alla domanda dell'OP e IMO è un po 'fuorviante.
joniba

Questo è proprio ciò di cui avevo bisogno per la migrazione da MongoDB Atlas teste anche per evitare di avere più connessioni. Tuttavia, anche io .dballa fine ( const v1 = mongoose.connection.useDb('test').db) poiché il vecchio db non ha bisogno di essere gestito da manguste.
Polv

37

Come approccio alternativo, Mongoose esporta un costruttore per una nuova istanza nell'istanza predefinita. Quindi qualcosa del genere è possibile.

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

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

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

Ciò è molto utile quando si lavora con origini dati separate e anche quando si desidera avere un contesto di database separato per ogni utente o richiesta. Dovrai stare attento, poiché è possibile creare MOLTE connessioni quando lo fai. Assicurati di chiamare disconnect () quando le istanze non sono necessarie e anche di limitare la dimensione del pool creato da ciascuna istanza.


1
è questo un altro modo per scrivere "sopra la risposta" ?
pravin

11
Questa non è la risposta di cui sopra, è meglio. La risposta sopra installa più copie di Mongoose, inutilmente.
Martín Valdés de León

come farei le query utilizzando questo metodo?
shahidfoy

2
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
Abdallah Al Barmawi

In effetti funziona meglio nel mio caso poiché ho credenziali completamente diverse per ogni connessione, figuriamoci modelli e database.
tzn

0

Soluzione un po 'ottimizzata (almeno per me). scrivilo in un file db.js e richiedilo dove richiesto e chiamalo con una chiamata di funzione e sei a posto.

   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;
    };
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.