Mungo und mehrere Datenbanken in einem einzigen node.js-Projekt

121

Ich mache ein Node.js-Projekt, das Unterprojekte enthält. Ein Unterprojekt wird eine Mongodb-Datenbank haben und Mongoose wird zum Umschließen und Abfragen von db verwendet. Aber das Problem ist

  • Mongoose erlaubt nicht die Verwendung mehrerer Datenbanken in einer einzigen Mungo-Instanz, da die Modelle auf einer Verbindung basieren.
  • Um mehrere Mungo-Instanzen zu verwenden, erlaubt Node.js nicht mehrere Modulinstanzen, da das Caching-System vorhanden ist require(). Ich weiß, dass das Modul-Caching in Node.js deaktiviert wird, aber ich denke, dass dies nicht die gute Lösung ist, da nur Mungo benötigt wird.

    Ich habe versucht, createConnection()und openSet()in Mungo zu verwenden, aber es war nicht die Lösung.

    Ich habe versucht, die Mungo-Instanz ( http://blog.imaginea.com/deep-copy-in-javascript/ ) tief zu kopieren , um neue Mungo-Instanzen an das Unterprojekt zu übergeben, aber es wird geworfen RangeError: Maximum call stack size exceeded.

Ich möchte wissen, ob es überhaupt möglich ist, mehrere Datenbanken mit Mungo oder eine Problemumgehung für dieses Problem zu verwenden. Weil ich denke, Mungo ist ziemlich einfach und schnell. Oder andere Module als Empfehlungen?

Schüler
quelle

Antworten:

37

Eine Sache, die Sie tun können, ist, dass Sie möglicherweise Unterordner für jedes Projekt haben. Installieren Sie also Mungo in diesen Unterordnern und benötigen Sie () Mungo aus eigenen Ordnern in jeder Unteranwendung. Nicht vom Projektstamm oder vom globalen. Also ein Teilprojekt, eine Mungo-Installation und eine Mungo-Instanz.

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

In den Dateien db_access.js

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

Jetzt können Sie mit Mungo auf mehrere Datenbanken zugreifen.

yemaw
quelle
2
Dies bedeutet, dass jedes Projekt eine eigene Verbindung hat. Sie können keine 100.000 Verbindungen verwalten. Ich denke, es wäre besser, einen useDbBefehl zu verwenden, der denselben Verbindungspool verwendet.
Xpepermint
1
xpepermint können Sie ein Beispiel für useDb zeigen - Ich habe dieses Problem derzeit stackoverflow.com/questions/37583198/…
Lion789
4
Dies scheint eine enorme Belastung für das Projekt zu sein. Glaubst du nicht?
Eshwar Prasad Yaddanapudi
1
Es ist absolut in Ordnung, pro Anwendung einige verschiedene Verbindungsinstanzen (z. B. für eine Benutzer-DB, eine Sitzungs-DB und für Anwendungsdaten) zu haben. Es ist keine große Belastung oder wird Skalierungsprobleme verursachen und ist ein häufiger Anwendungsfall.
Iain Collins
Du bist der Beste, mein Freund! vielen Dank! Für mich geht das! Vielen Dank!
Biruel Rick
213

Nach dem Fein Handbuch , createConnection() kann verwendet werden , um mehrere Datenbanken zu verbinden.

Sie müssen jedoch für jede Verbindung / Datenbank separate Modelle erstellen:

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' }
}));

Ich bin mir ziemlich sicher, dass Sie das Schema zwischen ihnen teilen können, aber Sie müssen überprüfen, um sicherzugehen.

Robertklep
quelle
4
Ja, benannte Verbindungen und ein gemeinsames Schema sind meiner Meinung nach der richtige Weg. Jede Verbindung benötigt ein eindeutiges Modell gemäß Roberts Beispiel.
Simon Holmes
21
useDb()In 3.8 ist auch eine Kasse verfügbar, um den zugrunde liegenden Verbindungspool
freizugeben
1
Angenommen, ich habe eine automatisch generierte Datenbank (z. B. n Datenbanknummer). Nicht einer oder zwei. Gibt es eine Möglichkeit, eine Verbindung zu diesen herzustellen, ohne für jede Datenbank ein eigenes Modell zu erstellen?
Anooj Krishnan G
1
@AnoojKrishnanG Ich denke nicht, dass das möglich ist, nein. Sie müssen das Modell für jede Datenbank separat erstellen. Wie ich bereits in meiner Antwort angegeben habe, können Sie die Schemas möglicherweise unter den Verbindungen teilen , was einige Codierungszeit sparen kann.
Robertklep
1
Sie können das Schema für die verschiedenen Modelle und damit für DBs freigeben. var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
gewähren
41

Ziemlich spät, aber das könnte jemandem helfen. Bei den aktuellen Antworten wird davon ausgegangen, dass Sie für Ihre Verbindungen und Modelle dieselbe Datei verwenden.

Im wirklichen Leben besteht eine hohe Wahrscheinlichkeit, dass Sie Ihre Modelle in verschiedene Dateien aufteilen. Sie können so etwas in Ihrer Hauptdatei verwenden:

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

const db = mongoose.connection;

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

Genau so wird es in den Dokumenten beschrieben. Führen Sie dann in Ihren Modelldateien folgende Schritte aus:

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;

Wobei myDB Ihr Datenbankname ist.

Tahnik Mustasin
quelle
Vielen Dank - Ich konnte 3 verschiedene Datenbanken in einer einzigen Anwendung verwenden, indem ich Folgendes verwendete: const mongoose = require ('mongoose'); const Schema = mongoose.Schema; const mySchema = neues Schema ({}); const mydbvar = mongoose.connection.useDb ('mydb') module.exports = mydbvar.model ('myCollection', MySchema);
Johnathan Enslin
2
Auf jeden Fall das beste und realistischste Beispiel. Stellen Sie eine Verbindung zur Standarddatenbank her (genau wie bei Verwendung von SQL Server), und nutzen Sie useDb, um Ihre DML auf die entsprechende Datenbank auszurichten. (Sehr hilfreich, um Ihre Benutzer in einer Datenbank und Ihre Daten in einer anderen zu halten.) Sie müssen nicht mehrere Verbindungen herstellen, wenn Sie letztendlich Anforderungen an denselben Server senden. Wenn Sie sich mit zwei verschiedenen Servern verbinden, ist das ein anderer Fischkessel.
Newclique
2
Wie @Wade sagte, funktioniert diese Lösung meines Wissens nur, wenn sich alle Datenbanken auf demselben Server befinden. Es ist nicht klar, ob dies die Frage des OP beantwortet und IMO etwas irreführend ist.
Joniba
Dies ist genau das, was ich für die Migration von MongoDB Atlas von testund auch zur Vermeidung mehrerer Verbindungen benötigte. Allerdings habe ich auch .dbam Ende ( const v1 = mongoose.connection.useDb('test').db) da die alte Datenbank nicht mungo verwaltet werden muss.
Polv
36

Als alternativen Ansatz exportiert Mongoose einen Konstruktor für eine neue Instanz in die Standardinstanz. So etwas ist also möglich.

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

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

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

Dies ist sehr nützlich, wenn Sie mit separaten Datenquellen arbeiten und wenn Sie für jeden Benutzer oder jede Anforderung einen separaten Datenbankkontext haben möchten. Sie müssen vorsichtig sein, da dabei viele Verbindungen hergestellt werden können. Stellen Sie sicher, dass Sie connectect () aufrufen, wenn keine Instanzen benötigt werden, und die von jeder Instanz erstellte Poolgröße begrenzen.

Eric
quelle
1
Ist dies eine andere Möglichkeit, 'Above Answer' zu schreiben ?
Pravin
11
Dies ist nicht die obige Antwort, es ist besser. Die obige Antwort installiert unnötigerweise mehrere Kopien von Mongoose.
Martín Valdés de León
Wie würde ich mit dieser Methode Abfragen stellen?
Shahidfoy
2
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
Abdallah Al Barmawi
0

Eine etwas optimierte (zumindest für mich) Lösung. Schreiben Sie dies in eine Datei db.js und fordern Sie dies an, wo immer dies erforderlich ist, und rufen Sie es mit einem Funktionsaufruf auf, und Sie können loslegen.

   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
quelle