Использование нескольких баз данных Mongodb с Meteor.js

Возможно ли, чтобы 2 Meteor.Collections извлекали данные с 2 разных серверов баз данных mongdb?

Dogs = Meteor.Collection('dogs')        // mongodb://192.168.1.123:27017/dogs
Cats = Meteor.Collection('cats')        // mongodb://192.168.1.124:27017/cats

person Athena Wisdom    schedule 12.12.2013    source источник
comment
Интересно, а зачем вам это?   -  person WiredPrairie    schedule 12.12.2013


Ответы (3)


Обновить

Теперь можно подключаться к удаленным/нескольким базам данных:

var database = new MongoInternals.RemoteCollectionDriver("<mongo url>");
MyCollection = new Mongo.Collection("collection_name", { _driver: database });

Где <mongo_url> — это URL-адрес mongodb, например mongodb://127.0.0.1:27017/meteor (с именем базы данных)

На данный момент у этого есть один недостаток: нет Oplog.

Старый ответ

На данный момент это невозможно. Каждое метеорное приложение привязано к одной базе данных.

Есть несколько способов обойти это, но это может быть сложнее, чем стоит:

Один из вариантов — использовать отдельное приложение Meteor.

В другом вашем метеорном приложении (пример работы на порту 6000 на той же машине). У вас все еще может быть реактивность, но вам нужно прокси вставлять, удалять и обновлять через вызов метода

Сервер:

Cats = Meteor.Collection('cats')

Meteor.publish("cats", function() {
    return Cats.find();
});

Meteor.methods('updateCat, function(id, changes) {
    Cats.update({_id: id}, {$set:changes});
});

Ваше текущее приложение Meteor:

var connection = DDP.connect("http://localhost:6000");

connection.subscribe("cats");
Cats = Meteor.Collection('cats', {connection: connection});

//To update a collection
Cats.call("updateCat", <cat_id>, <changes);

Другой вариант - пользовательское соединение mongodb

При этом используется собственный драйвер node js mongodb.

Это подключение к базе данных, как если бы вы делали это в любом другом приложении node js.

Доступной реактивности нет, и вы не можете использовать наборы типов new Meteor.Collection.

var mongodb = Npm.require("mongodb"); //or var mongodb = Meteor.require("mongodb") //if you use npm package on atmosphere

var db = mongodb.Db;
var mongoclient = mongodb.MongoClient;
var Server = mongodb.Server;

var db_connection = new Db('cats', new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize: 4}), {w:0, native_parser: false});

db.open(function(err, db) {
    //Connected to db 'cats'

    db.authenticate('<db username>', '<db password>', function(err, result) {
      //Can do queries here
      db.close();
   });
});
person Tarang    schedule 12.12.2013
comment
На самом деле возможно иметь коллекцию, поддерживаемую другим сервером базы данных; см. мой ответ ниже. - person Emily; 16.09.2014
comment
@Эмили, отлично, я долго этого ждал. На клиенте мы используем ту же обычную коллекцию, да? - person Tarang; 16.09.2014
comment
Куда вы поместите эти две строчки кода? В блоке if (Meteor.isServer) {}, в Meteor.startup(function () {}); блокировать ? - person JoeTidee; 01.03.2015
comment
@JoePrivett в любом месте на сервере. - person Tarang; 05.05.2015
comment
Это работает, если базы данных имеют разные имена коллекций, но не в том случае, если у вас одинаковые имена коллекций в обеих базах данных. Кто-нибудь знает как это сделать? - person ajamardo; 14.04.2016
comment
Любая идея, как заставить это работать в реакции? Ошибка на стороне клиента при экспорте базы данных (как и при обычной коллекции в реакции/метеоре). Обертка в Meteor.isServer() не помогает. - person redcap3000; 06.01.2017

На самом деле это возможно, используя внутренний интерфейс:

var d = new MongoInternals.RemoteCollectionDriver("<mongo url>");
C = new Mongo.Collection("<collection name>", { _driver: d });
person Emily    schedule 15.09.2014
comment
Куда вы поместите эти две строчки кода? В блоке if (Meteor.isServer) {}, в Meteor.startup(function () {}); блокировать ? Я продолжаю получать ReferenceError: C не определен. - person JoeTidee; 01.03.2015
comment
Обратите внимание, что это должно выполняться ТОЛЬКО на сервере, то есть внутри блока if (Meteor.isServer) {. Вам также нужно будет добавить C = new Mongo.Collection(‹название коллекции›); к вашему if (Meteor.isClient) { block. - person JoeTidee; 01.03.2015
comment
Быстрый совет, если вы обнаружите, что ваши коллекции пусты: обязательно укажите имя базы данных в конце URL-адреса mongodb, он автоматически завершится ошибкой, и ваши коллекции просто будут отображаться пустыми. Если вы хотите подключиться к другому локальному экземпляру mongodb метеора, который вы запускали, скажем, на порту 4444, а mongo находится на 4445, URL-адрес будет выглядеть так: mongodb://127.0.0.1:4445/meteor - person Shwaydogg; 05.01.2016

Ответ ДА: можно настроить несколько Meteor.Collections для получения данных с разных серверов базы данных mongdb.

Как ответ от @Akshat, вы можете инициализировать свой собственный экземпляр MongoInternals.RemoteCollectionDriver, с помощью которого можно создать Mongo.Collection.

Но вот еще о чем поговорить. Вопреки ответу @Akshat, я считаю, что поддержка Oplog по-прежнему доступна при таких обстоятельствах.

При инициализации пользовательского MongoInternals.RemoteCollectionDriver НЕ ЗАБУДЬТЕ указать URL Oplog:

var driver = new MongoInternals.RemoteCollectionDriver(
    "mongodb://localhost:27017/db", 
    {
      oplogUrl: "mongodb://localhost:27017/local"
    });
var collection = new Mongo.Collection("Coll", {_driver: driver});

Под капотом

Как описано выше, активировать поддержку Oplog достаточно просто. Если вы хотите узнать, что скрывается за этими двумя строками кода, вы можете продолжить чтение поста до конца.

В конструкторе RemoteCollectionDriver будет создан базовый MongoConnection:

MongoInternals.RemoteCollectionDriver = function (
  mongo_url, options) {
  var self = this;
  self.mongo = new MongoConnection(mongo_url, options);
}; 

Хитрость заключается в следующем: если MongoConnection создается с предоставленным oplogUrl, будет инициализирован OplogHandle, и он начнет отслеживать Oplog (исходный код):

if (options.oplogUrl && ! Package['disable-oplog']) {  
  self._oplogHandle = new OplogHandle(options.oplogUrl, self.db.databaseName);
  self._docFetcher = new DocFetcher(self);
}

Как описано в этом блоге: Meteor.publish внутренне вызывает Cursor.observeChanges для создания экземпляра ObserveHandle. , который автоматически отслеживает любые будущие изменения, происходящие в базе данных.

В настоящее время существует два типа драйверов-наблюдателей: устаревший PollingObserveDriver, использующий стратегию опроса и сравнения, и OplogObseveDriver, эффективно использующий Oplog-хвост для отслеживания изменений данных. Чтобы решить, какой из них применить, observeChanges выполняет следующую процедуру (исходный код):

var driverClass = canUseOplog ? OplogObserveDriver : PollingObserveDriver;
observeDriver = new driverClass({
  cursorDescription: cursorDescription,
  mongoHandle: self,
  multiplexer: multiplexer,
  ordered: ordered,
  matcher: matcher,  // ignored by polling
  sorter: sorter,  // ignored by polling
  _testOnlyPollCallback: callbacks._testOnlyPollCallback
});

Чтобы сделать canUseOplog истинным, необходимо выполнить несколько требований. Самый минимальный: базовый экземпляр MongoConnection должен иметь действительный OplogHandle. Именно по этой причине нам нужно указать oplogUrl при создании MongoConnection

person Haizi    schedule 18.12.2015
comment
это нужно отметить как правильный ответ! Я пометил этот пост в надежде, что администратор или ОП сможет изменить ответ! - person kroe; 08.08.2017