Tek node.js projesinde Mongoose ve çoklu veritabanı


123

Alt projeler içeren bir Node.js projesi yapıyorum. Bir alt proje bir Mongodb veritabanına sahip olacak ve Mongoose db'yi sarmak ve sorgulamak için kullanılacak. Ama sorun şu ki

  • Mongoose, modeller tek bir bağlantı üzerine kurulduğundan, tek firavun faresi örneğinde birden çok veri tabanının kullanılmasına izin vermez.
  • Birden çok firavun faresi örneğini kullanmak için, Node.js, içinde önbelleğe alma sistemi olduğu için birden fazla modül örneğine izin vermez require(). Node.js'de modül önbelleğini devre dışı bırakmayı biliyorum, ancak bunun sadece firavun faresi için gerekli olduğu için iyi bir çözüm olmadığını düşünüyorum.

    Ben kullanımına denedim createConnection()ve openSet()firavunfaresi içinde, ama bu çözüm değildi.

    Yeni firavun faresi örneklerini alt projeye geçirmek için firavun faresi örneğini ( http://blog.imaginea.com/deep-copy-in-javascript/ ) derin kopyalamaya çalıştım , ancak fırlatıyor RangeError: Maximum call stack size exceeded.

Firavun faresi ile birden fazla veritabanı kullanmanın bir yolu var mı, yoksa bu sorun için herhangi bir çözüm var mı? Çünkü firavun faresinin oldukça kolay ve hızlı olduğunu düşünüyorum. Veya tavsiye olarak başka modüller?

Yanıtlar:


38

Yapabileceğiniz bir şey, her proje için alt klasörleriniz olabilir. Bu nedenle, mongoose'u bu alt klasörlere yükleyin ve her alt uygulamada kendi klasörlerinden () firavun faresi isteyin. Proje kökünden veya genelden değil. Yani bir alt proje, bir firavun faresi kurulumu ve bir firavun faresi örneği.

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

Foo_db_connect.js içinde

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

Bar_db_connect.js içinde

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

Db_access.js dosyalarında

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

Artık mongoose ile birden fazla veritabanına erişebilirsiniz.


2
Bu, her projenin kendi bağlantısına sahip olacağı anlamına gelir. 100.000 bağlantıyı yönetemeyeceksiniz. useDbAynı bağlantı havuzunu kullanan bir komut kullanmanın daha iyi olacağını düşünüyorum .
xpepermint

1
xpepermint useDb için bir örnek gösterebiliyor musunuz - Şu anda bu sorunu yaşıyorum stackoverflow.com/questions/37583198/…
Lion789

4
Bu, proje üzerinde çok büyük bir yük gibi görünüyor. öyle değil mi
Eshwar Prasad Yaddanapudi 02

1
Uygulama başına birkaç farklı bağlantı eşgörünümüne sahip olmak (örneğin, bir Kullanıcı DB, bir Oturum DB ve uygulama verileri için) kesinlikle iyidir. Bu, "çok büyük bir yük" değildir veya ölçekleme sorunlarına neden olmaz ve yaygın bir kullanım örneğidir.
Iain Collins

Sen en iyi arkadaşımsın çok teşekkürler! benim için çalışıyor! Teşekkürler!
Biruel Rick

215

Göre ince kılavuzu , createConnection() olabilir birden fazla veritabanı bağlanmak için kullanılabilir.

Ancak, her bağlantı / veritabanı için ayrı modeller oluşturmanız gerekir:

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

Şemayı aralarında paylaşabileceğinizden oldukça eminim, ancak emin olmak için kontrol etmelisiniz.


4
Evet, adlandırılmış bağlantılar ve paylaşılan bir şema bence gitmenin yolu. Robert'ın örneğine göre her bağlantının benzersiz bir modele ihtiyacı olacaktır.
Simon Holmes

21
Ayrıca useDb(), alttaki bağlantı havuzunu paylaşmak için 3.8'de ödeme yapılabilir: github.com/LearnBoost/mongoose/wiki/…
aaronheckmann

1
Otomatik oluşturulmuş bir veritabanım olduğunu varsayalım (n sayıda veritabanı söyle). Bir ya da iki değil. Her veritabanı için ayrı bir model oluşturmadan bunlara bağlanmanın bir yolu var mı?
Anooj Krishnan G

1
@AnoojKrishnanG Bunun mümkün olduğunu sanmıyorum, hayır. Modeli her veritabanı için ayrı ayrı oluşturmanız gerekir. Ancak, cevabımda daha önce de belirttiğim gibi, şemaları bağlantılar arasında paylaşabilirsiniz , bu da kodlama zamanından tasarruf sağlayabilir.
robertklep

1
Şemayı farklı modeller ve dolayısıyla DB'ler arasında paylaşabilirsiniz. var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
hibe

42

Oldukça geç ama bu birine yardımcı olabilir. Mevcut cevaplar, bağlantılarınız ve modelleriniz için aynı dosyayı kullandığınızı varsayar.

Gerçek hayatta, modellerinizi farklı dosyalara bölme olasılığınız yüksektir. Ana dosyanızda buna benzer bir şey kullanabilirsiniz:

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

const db = mongoose.connection;

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

bu tam da belgelerde anlatıldığı gibi. Ve sonra model dosyalarınızda aşağıdakine benzer bir şey yapın:

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;

MyDB, veritabanı adınızdır.


Teşekkürler - Tek bir uygulamada 3 farklı veri tabanını kullanabildim: const mongoose = require ('mongoose'); const Schema = firavun faresi.Schema; const mySchema = yeni Şema ({}); const mydbvar = mongoose.connection.useDb ('mydb') module.exports = mydbvar.model ('myCollection', MySchema);
Johnathan Enslin

2
Kesinlikle en iyi ve en gerçek dünya örneği. Varsayılan veritabanına bağlanın (tıpkı SQL Server gibi bir şey kullanıyormuşsunuz gibi) ve ardından DML'nizi uygun veritabanında hedeflemek için useDb'den yararlanın. (Kullanıcılarınızı bir veritabanında ve verilerinizi başka bir veritabanında tutmak için çok yararlıdır.) Sonuçta aynı sunucuya istek gönderirken birden fazla bağlantı kurmaya gerek yoktur. Şimdi, iki farklı sunucuya bağlanıyorsanız, bu farklı bir su ısıtıcısıdır.
Newclique

2
@Wade'in dediği gibi, anladığım kadarıyla bu çözüm yalnızca tüm veritabanları aynı sunucuda olduğunda çalışıyor. Bunun OP'nin sorusunu yanıtlayıp yanıtlamadığı net değil ve IMO biraz yanıltıcı.
joniba

Bu, MongoDB Atlas'tan geçiş için testve ayrıca birden fazla bağlantıdan kaçınmak için ihtiyacım olan şeydi . Bununla birlikte, ben de .dbsonunda ( const v1 = mongoose.connection.useDb('test').db) eski db'nin firavun faresi yönetilmesine gerek olmadığı için.
Polv

37

Alternatif bir yaklaşım olarak Mongoose, varsayılan örnekte yeni bir örnek için bir yapıcı dışa aktarır. Yani bunun gibi bir şey mümkün.

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

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

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

Bu, ayrı veri kaynaklarıyla çalışırken ve ayrıca her kullanıcı veya istek için ayrı bir veritabanı bağlamına sahip olmak istediğinizde çok kullanışlıdır. Bunu yaparken çok sayıda bağlantı oluşturmak mümkün olduğu için dikkatli olmanız gerekecektir. Örnekler gerekmediğinde disconnect () öğesini çağırdığınızdan ve ayrıca her örnek tarafından oluşturulan havuz boyutunu sınırladığınızdan emin olun.


1
Bu, 'Yanıtın Üstünde' yazmanın başka bir yolu mu?
2016

11
Bu yukarıdaki cevap değil, daha iyi. Yukarıdaki cevap, gereksiz yere Mongoose'un birden çok kopyasını yükler.
Martín Valdés de León

bu yöntemi kullanarak nasıl sorgu yaparım?
shahidfoy

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

Aslında, modelleri ve veritabanları bir yana, her bağlantı için tamamen farklı kimlik bilgilerine sahip olduğum için benim durumumda daha iyi çalışıyor.
tzn

0

Biraz optimize edilmiş (en azından benim için) çözüm. bunu bir db.js dosyasına yazın ve bunu istediğiniz yere yazın ve onu bir işlev çağrısı ile çağırın ve gitmeniz iyi olur.

   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;
    };
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.