在 Meteor.js 中使用多个 Mongodb 数据库

Posted

技术标签:

【中文标题】在 Meteor.js 中使用多个 Mongodb 数据库【英文标题】:Using Multiple Mongodb Databases with Meteor.js 【发布时间】:2013-12-30 09:45:58 【问题描述】:

2Meteor.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

【问题讨论】:

很好奇,你为什么要这么做? 【参考方案1】:

更新

现在可以连接到远程/多个数据库:

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

其中&lt;mongo_url&gt; 是一个mongodb url,例如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原生驱动。

这就像在任何其他节点 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();
   );
);

【讨论】:

实际上可以有一个由不同的数据库服务器支持的集合;请参阅下面的答案。 @Emily 太好了,我已经等了很长时间了。在客户端我们使用相同的普通集合是吗? 这两行代码放在哪里了?在 if (Meteor.isServer) 块中,在 Meteor.startup(function () );阻止? @JoePrivett 服务器上的任何位置。 如果数据库具有不同的集合名称,则此方法有效,但如果您在两个数据库中具有相同的集合名称,则无效。有人知道怎么做吗?【参考方案2】:

这实际上是可能的,使用内部接口:

var d = new MongoInternals.RemoteCollectionDriver("<mongo url>");
C = new Mongo.Collection("<collection name>",  _driver: d );

【讨论】:

这两行代码放在哪里了?在“if (Meteor.isServer) ”块中,在“Meteor.startup(function () );”中堵塞 ?我不断收到“ReferenceError: C is not defined”。 请注意,这只能在服务器上运行,即在“if (Meteor.isServer) ”块内。您还必须添加“C = new Mongo.Collection("");"到你的“if (Meteor.isClient) ”块。 快速提示如果你发现你的集合是空的:确保在 mongodb url 的末尾包含数据库名称,它会默默地失败,你的集合只会显示为空。如果您想连接到另一个在端口 4444 上运行的本地流星 mongodb 实例,而 mongo 在 4445 上,则 url 将如下所示:mongodb://127.0.0.1:4445/meteor【参考方案3】:

答案是YES:可以设置多个 Meteor.Collections 从不同的 mongdb 数据库服务器检索数据。

作为@Akshat 的回答,您可以初始化自己的MongoInternals.RemoteCollectionDriver 实例,通过它可以创建Mongo.Collections。

但这里还有点要说的。与@Akshat 的回答相反,我发现在这种情况下仍然可以使用 Oplog 支持。

初始化自定义MongoInternals.RemoteCollectionDriver时,不要忘记指定Oplog url:

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(source code):

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

正如blog 所描述的:Meteor.publish 在内部调用Cursor.observeChanges 来创建一个ObserveHandle 实例,该实例会自动跟踪数据库中未来发生的任何更改。

目前有两种观察者驱动程序:采用 poll-and-diff 策略的旧版PollingObserveDriver,以及有效使用 Oplog-tailing 来监控数据更改的OplogObseveDriver。要决定申请哪一个,observeChanges 采用以下过程 (source code):

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。这就是为什么我们需要在创建 MongoConnection 时指定 oplogUrl 的确切原因

【讨论】:

这需要标记为正确答案!我已标记此帖子,希望管理员或 OP 可以切换答案!

以上是关于在 Meteor.js 中使用多个 Mongodb 数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何更新meteor.js中的Mongodb集合?

MongoDB / Meteor / 将 MONGO_URL 导出到已部署的应用程序

MongoDB / Meteor / 将 MONGO_URL 导出到已部署的应用程序

Meteor js:使用#each 来迭代和渲染博客的多个 html 文件中的模板

如何将meteor.js db 导入远程mongo

Meteor JS 可以在除 iOS 设备之外的所有设备上连接到 compose.io 吗?