【问题标题】:Meteor database connection流星数据库连接
【发布时间】:2015-02-28 22:50:01
【问题描述】:

我正在尝试连接到作为 Meteor 应用程序位于机器上的 Mongo 数据库。这是我的应用程序中的两个文件:

a.js:

if (Meteor.isServer) {

    var database = new MongoInternals.RemoteCollectionDriver("mongodb://127.0.0.1:3001/meteor");
    Boxes = new Mongo.Collection("boxes", { _driver: database });
    Meteor.publish('boxes', function() {
        return Boxes.find(); 
    }); 
}

b.js:

if (Meteor.isClient) {
    Meteor.subscribe('boxes');
    Template.homeCanvasTpl.helpers({
        boxes: function () {
            return Boxes.find({});
        }
    });
}

但我不断收到“模板助手中的异常:ReferenceError:未定义框”错误 - 有什么想法吗?

【问题讨论】:

  • 您尚未在客户端定义集合。您必须在服务器和客户端上都定义它。我认为您在客户端上定义它时不必传递任何第二个参数,因为您仍将使用与服务器的默认连接。

标签: mongodb meteor


【解决方案1】:

如何使用 Meteor 连接到 MongoDB?

场景 A:默认使用内置数据库

这比你做的要简单得多。当您运行meteor 时,您实际上使用 Meteor 服务器启动了一个数据库,其中 Meteor 侦听端口 3000 和端口 3001 上的数据库。 Meteor 应用程序已经在端口 3001 上连接到该数据库并使用名为 meteor 的数据库。没有必要回退到MongoInternals.RemoteCollectionDriver。只需删除该代码并将其更改为:

 Boxes = new Mongo.Collection("boxes"); // use default MongoDB connection

场景 B:默认使用不同的数据库

使用MONGO_URL 环境变量,您可以在启动 Meteor 服务器时将连接字符串设置为 MongoDB。您可以准确指定连接的位置和方式,而不是本地端口 3001 数据库或未经身份验证的连接。像这样启动你的 Meteor 服务器:

$ MONGO_URL=mongodb://user:password@localhost:27017/meteor meteor

如果不需要身份验证,您也可以省略命令的 user:password@ 部分。

场景 C:从同一个 Meteor 应用连接到第二个(第三个等)数据库

现在我们需要使用MongoInternals.RemoteCollectionDriver。如果您希望使用另一个不是在启动 Meteor 服务器时定义的默认数据库的数据库,您应该使用您的方法。

var database = new MongoInternals.RemoteCollectionDriver('mongodb://user:password@localhost:27017/meteor');
var numberOfDocs = database.open('boxes').find().count();

奖励:为什么不能将MongoInternalsMongo.Collection 一起使用?

作为the docs indicate,您不应该将任何Mongo 连接传递给new Mongo.Collection() 命令,而只能传递到另一个Meteor 实例的连接。这意味着,如果您使用 DDP.connect 连接到不同的服务器,您可以使用您的代码 - 但您不应该将 MongoInternalsMongo.Collection 混合使用 - 它们不能很好地协同工作。

【讨论】:

  • 那么声明远程集合的最简单方法是什么?类似var Boxes = database.open('boxes') 的东西有用吗?
  • 这并不是那么简单,因为 Collection 中有很多“魔法”发生在简单的数据库集合之外(即反应性、跟踪 oplog 等)。如果您可以在没有这些特征的情况下做到这一点,那么场景 C 可以让您快速轻松地访问远程 DB coll,它只是没有反应性。
  • 注意:集合可能看起来是空的,您需要进行插入才能看到数据。
【解决方案2】:

根据上述 cmets 中 saimeunt 的反馈,他/她指出,MongoInternals 不适用于 Meteor 应用程序的客户端部分。因此,解决方案是在“Boxes = new Mongo.Collection("boxes");”行中添加到客户端逻辑 - 这是最终的工作解决方案:

a.js:

if (Meteor.isServer) {

    var database = new MongoInternals.RemoteCollectionDriver("mongodb://127.0.0.1:3001/meteor");
    Boxes = new Mongo.Collection("boxes", { _driver: database });
    Meteor.publish('boxes', function() {
        return Boxes.find(); 
    }); 
}

b.js

if (Meteor.isClient) {
    Boxes = new Mongo.Collection("boxes");
    Meteor.subscribe('boxes');
    Template.homeCanvasTpl.helpers({
        boxes: function () {
            return Boxes.find({});
        }
    });
}

【讨论】:

  • 别介意上面的评论。看来你想通了。 :-)
【解决方案3】:

Meteor 有两种不同的环境:在 Node.JS 上运行的服务器环境和在浏览器中运行的客户端环境。

在您的代码中,您仅在服务器环境中声明 Boxes Mongo 集合,您需要将此声明从 Meteor.isServer 条件中取出(顺便说一句,不要使用这些,将您的代码分隔在 server/ 中, client/lib/ 目录)。

另外,不确定您是否需要以这种方式连接到 MongoDB,也许您应该查看 MONGO_URL 环境变量,它可能已经满足您的需求? (提供到远程(或本地)Mongo 服务器的 mongo 连接 URL)。

【讨论】:

  • 我将声明移出 Meteor.isServer 条件(上方),现在我收到此错误:“未定义 MongoInternals” - 有什么想法吗? p.s.我正在尝试使用此方法,因为它在其他地方的 Stack Overflow 上被推荐为替代 MONGO_URL 的方法。
  • 然后尝试使用 2 个声明,一个在服务器中使用 MongoInternals 东西,另一个在客户端没有。
  • 使用 2 个声明与在任何 isClient/isServer 块之外有一个声明的文档相矛盾,因此生成的变量可以在整个应用程序中全局访问。
  • 再次阅读我的答案:Meteor 中有 2 个环境,因此变量在整个应用程序中永远不会真正可用,单个声明始终会生成对应于 2 个不同环境的 2 个不同版本的变量。在您的特定情况下,您无法在两个环境中无缝声明集合,因为 MongoInternals 在客户端上不可用,因此您必须依赖 2 个单独的声明。
  • 我再次阅读了您的答案,但没有看到任何关于您说客户无法使用 MongoInternals 的信息。现在您已经提到了这一点,您能否为我和其他人指出这方面的文档方向?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
  • 2013-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多