Мангуста та декілька баз даних в одному проекті node.js


123

Я роблю проект Node.js, який містить підпроекти. Один підпроект матиме одну базу даних Mongodb, і Mongoose буде використовуватися для обгортання та запиту db. Але проблема є

  • Mongoose не дозволяє використовувати безліч баз даних в одному екземплярі мангусти, оскільки моделі побудовані на одному з'єднанні.
  • Щоб використовувати кілька екземплярів мангустів, Node.js не дозволяє декілька екземплярів модулів, оскільки в ньому є система кешування require(). Я знаю, що відключити кешування модулів у Node.js, але я думаю, що це не гарне рішення, оскільки це потрібно лише мангусту.

    Я намагався використовувати createConnection()і openSet()в мангусті, але це не було рішенням.

    Я спробував глибоко скопіювати екземпляр мангусти ( http://blog.imaginea.com/deep-copy-in-javascript/ ), щоб передати нові екземпляри мангусти до підпроекту, але він кидає RangeError: Maximum call stack size exceeded.

Хочу знати, чи все-таки для використання цієї проблеми можна використовувати декілька баз даних із мангустом чи якісь шляхи вирішення? Тому що я думаю, що мангуст досить легко і швидко. Або будь-які інші модулі як рекомендації?

Відповіді:


38

Одне, що ви можете зробити, це те, що ви можете мати підпапки для кожного проекту. Отже, встановіть мангуст у ці папки та вимагайте () мангуста з власних папок у кожному додатку. Не з кореня проекту чи з глобального. Отже, один підпроект, одна установка мангуста та один екземпляр мангуста.

-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

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

В bar_db_connect.js

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

У файлах db_access.js

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

Тепер ви можете отримати доступ до декількох баз даних з мангустом.


2
Це означає, що кожен проект матиме свій зв’язок. Ви не зможете керувати з'єднаннями в 100 к. Я думаю, було б краще використовувати useDbкоманду, яка використовує той самий пул з'єднань.
xpepermint

1
xpepermint ви в змозі показати приклад useDb - я маю це питання в даний час stackoverflow.com/questions/37583198 / ...
Lion789

4
Це виглядає як величезне навантаження на проект. ти так не вважаєш?
Ешвар Прасад Ядданапуді

1
Маючи кілька різних примірників підключення (наприклад, для БД користувача, БД сесії та даних додатків) для кожної програми абсолютно добре. Це не є «великим тягарем» або не спричиняє проблем зі масштабуванням і є загальним випадком використання.
Ієн Коллінз

Ти найкращий мій друг! дуже дякую! це працює для мене! Дякую!
Біруель Рік

214

Згідно з прекрасним посібником , createConnection() його можна використовувати для підключення до декількох баз даних.

Однак вам потрібно створити окремі моделі для кожного з'єднання / бази даних:

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

Я майже впевнений, що ви можете поділитися схемою між ними, але вам потрібно перевірити, щоб переконатися.


4
Так, я вважаю, що названі з'єднання та спільна схема - це шлях. Кожне з'єднання потребує унікальної моделі, як на прикладі Роберта.
Саймон Холмс

21
Також useDb()можна отримати замовлення, доступне в 3.8, щоб поділитися базовим пулом зв’язків: github.com/LearnBoost/mongoose/wiki/…
aaronheckmann

1
Припустимо, у мене автоматично створена база даних (скажіть n номер бази даних). Не один чи два. Чи є спосіб підключитися до них без створення окремої моделі для кожної бази даних?
Anooj Krishnan G

1
@AnoojKrishnanG Я не думаю, що це можливо, ні. Вам потрібно створити модель проти кожної бази даних окремо. Однак, як я вже заявив у своїй відповіді, можливо, ви зможете поділитися схемою серед з'єднань, що може заощадити деякий час кодування.
robertklep

1
Ви можете поділитися схемою в різних моделях, а отже, і в БД. var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
дарувати

42

Досить пізно, але це може комусь допомогти. Поточні відповіді передбачають, що ви використовуєте той самий файл для своїх підключень та моделей.

У реальному житті є велика ймовірність, що ви розділите свої моделі на різні файли. Ви можете використовувати щось подібне у своєму головному файлі:

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

const db = mongoose.connection;

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

що саме так описано в документах. А потім у своїх модельних файлах виконайте щось на зразок наступного:

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 - ваше ім'я бази даних.


Дякую - мені вдалося використовувати 3 різні бази даних в межах однієї програми, використовуючи: const mongoose = need ('mongoose'); схема const = мангуста.Схема; const mySchema = нова схема ({}); const mydbvar = mongoose.connection.useDb ('mydb') module.exports = mydbvar.model ('myCollection', MySchema);
Джоннатан Енслін

2
Безумовно, найкращий і найреальніший приклад. Підключіться до db за замовчуванням (так само, як якщо б ви використовували щось на зразок SQL Server), а потім скористайтеся перевагою useDb для націлювання вашого DML на відповідну базу даних. (Дуже корисно для збереження ваших користувачів в одному db, а ваших даних в іншому.) Не потрібно починати встановлювати декілька з'єднань, коли в кінцевому підсумку ви надсилаєте запити на один і той же сервер. Тепер, якщо ви підключалися до двох різних серверів, це інший чайник з рибою.
Ньюклік

2
Як сказав @Wade, наскільки я розумію, це рішення працює лише тоді, коли всі бази даних знаходяться на одному сервері. Не ясно, чи це відповідає на питання ОП, і ІМО трохи вводить в оману.
joniba

Це саме те, що мені потрібно для міграції MongoDB Atlas з test, а також щоб уникнути декількох з'єднань. Однак я також .dbв кінці ( const v1 = mongoose.connection.useDb('test').db), оскільки старий db не повинен управляти мангустом.
Полв

37

Як альтернативний підхід, Mongoose експортує конструктор для нового екземпляра на примірник за замовчуванням. Тож щось подібне можливо.

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

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

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

Це дуже корисно при роботі з окремими джерелами даних, а також, коли ви хочете мати окремий контекст бази даних для кожного користувача чи запиту. Вам потрібно буде бути обережними, оскільки при цьому можливо створити багато зв’язків. Не забудьте зателефонувати disconnect (), коли екземпляри не потрібні, а також обмежте розмір пулу, створений кожним екземпляром.


1
це ще один спосіб написання "Над відповіддю" ?
pravin

11
Це не вищезазначена відповідь, це краще. Вищезгадана відповідь встановлює безліч копій Мангуста, без необхідності.
Martín Valdés de León

як я можу робити запити за допомогою цього методу?
шахідфой

2
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
Абдалла Аль Бармаві

Насправді краще працювати в моєму випадку, оскільки я маю абсолютно різні облікові дані для кожного з'єднання, не кажучи вже про моделі та бази даних.
тзн

0

Трохи оптимізоване (для мене принаймні) рішення. напишіть це у файл db.js і вимагайте цього куди завгодно, і зателефонуйте йому за допомогою виклику функції, і ви добре піти.

   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;
    };
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.