【问题标题】:Add single record to mongo collection with meteor使用流星将单个记录添加到 mongo 集合
【发布时间】:2015-08-19 19:01:26
【问题描述】:

我是 JavaScript 和流星框架的新用户,试图理解基本概念。首先,我想将单个文档添加到集合中而没有重复条目。

this.addRole = function(roleName){
   console.log(MongoRoles.find({name: roleName}).count());

   if(!MongoRoles.find({name: roleName}).count())
      MongoRoles.insert({name: roleName});
}

此代码在服务器和客户端上调用。客户端上的日志消息告诉我集合中没有条目。即使我多次刷新页面。

在服务器上,重复的条目被输入到集合中。我不知道为什么。可能我没有理解关键概念。有人可以向我指出吗?

Edit-1: 不,不再安装自动发布和不安全。但是我已经发布了 MongoRoles 集合(服务器端)并订阅了它(客户端)。此外,我为插入(客户端)创建了一个允许规则。

Edit-2:

非常感谢您向我展示了流星方法,但我想在不涉及服务器端方法的情况下做到这一点。让我们出于学术目的说。 ;-)

只是写了一个小例子:

客户:

Posts = new Mongo.Collection("posts");

Posts.insert({title: "title-1"});
console.log(Posts.find().count());

服务器:

Posts = new Mongo.Collection("posts");

Meteor.publish(null, function () {
  return Posts.find()
})

Posts.allow({
 insert: function(){return true}
})

如果我通过“meteor mongo”检查服务器数据库,它会告诉我客户端代码的每个插入都保存在那里。

每次我刷新页面时,客户端上的日志都会告诉我“1 个计数”。但我希望两者都一样。我做错了什么?

Edit-3:

我又回到了我原来的角色示例(对此感到抱歉)。只是以为我明白了,但我仍然一无所知。如果我检查变量“roleCount”,则始终响应 0。如何将正确的值加载到我的变量中?在插入集合之前检查文档是否存在的最佳方法是什么?猜猜 .find() 也是异步的?如果是这样,我怎样才能做到同步?如果我做对了,我必须等待该值(同步),因为我真的会对其进行中继。

共享环境(客户端和服务器):

Roles = new Mongo.Collection("jaqua_roles");

Roles.allow({
    insert: function(){return true}
})

var Role = function(){

this.addRole = function(roleName){      

    var roleCount = Roles.find({name: roleName}).count();
    console.log(roleCount);

    if(roleCount === 0){

        Roles.insert({name: roleName}, function(error, result){
            try{
                console.log("Success: " + result);
                var roleCount = Roles.find({name: roleName}).count();
                console.log(roleCount);
            } catch(error){

            }
        });
    }
};

this.deleteRole = function(){

};
}

role = new Role();
role.addRole('test-role');

仅服务器:

Meteor.publish(null, function () {
  return Roles.find()
})

【问题讨论】:

  • 是否安装了autopublish 包?尝试在终端中使用meteor list 来找出答案。
  • 我遵循@BraveKenny 的要求,并添加我关于insecure 包的问题。尝试在线完成教程 [这里]。(meteor.com/tutorials/blaze/creating-an-app) 之后一切都会更清楚
  • 抱歉,缺少信息。不,不再安装自动发布和不安全。但是我已经发布了 MongoRoles 集合(服务器端)并订阅了它(客户端)。此外,我为插入(客户端)创建了一个允许规则。感谢您的提示。我已经完成了本教程,并认为我明白了这一点。但显然我没有。据我了解,如果我在双方实现相同的功能,客户端数据库和服务器数据库应该相互同步。但我不知道为什么它不是我的情况。更糟糕的是,为什么服务器数据库中添加了多个条目?
  • 如果没有更多代码,很难判断发生了什么。你在哪里调用addRole 函数?
  • 在我的问题中添加了另一个示例。我只想为集合添加一些值。之后客户端和服务器数据库应该具有相同的值。在下一步中,我想根据客户端数据库中的值执行一些选项检查。我对异步方式(Meteor.methods)感到困惑。如果这样做,我将无法及时获得返回值,一切都会变得一团糟。

标签: mongodb meteor collections


【解决方案1】:

Meteor 的insert/update/remove 方法(客户端)不是一个好主意。潜在的安全隐患太多,真正修补任何漏洞需要花费大量的思考和时间。 Further reading这里。

我还想知道您从哪里拨打addRole。假设它仅从客户端触发,我会这样做:

客户端代码:

this.addRole = function(roleName){
  var roleCount = MongoRoles.find({name: roleName}).count();

  console.log(roleCount);

  if (roleCount === 0) {
    Meteor.call('insertRole', roleName, function (error, result) {
      if (error) {
        // check error.error and error.reason (if I'm remembering right)
      } else {
        // Success!
      }
    });
  }
}

我如何修改此代码以及为什么:

  1. 我创建了一个roleCount 变量,这样您就可以避免像那样调用MongoRoles.find() 两次,这种方法效率低下并且会消耗不需要的资源(CPU、磁盘I/O 等)。存储一次,然后引用变量,这样会更好。
  2. 检查数字时,尽量避免使用if (!count) 之类的操作。使用if (count === 0) 更清楚,并表明您正在引用一个数字。像if (!xyz) 这样的语句会让人认为这是一个布尔值(真/假)。
  3. 在 JavaScript 中始终使用===,除非您想故意进行松散的相等操作。 Read more 对此。
  4. 始终对if 和其他块使用开/关花括号,即使它只包含一行代码。这只是一个很好的做法,因此如果您决定稍后添加另一行,则不必将其包裹在大括号中。只是一个很好的练习。
  5. 将数据库插入更改为 Meteor 方法(见下文)。
  6. 旁注:我使用过 JavaScript (ES5),但由于您是 JavaScript 新手,我认为您应该 jump right into ES6。 ES 是 ECMAScript 的缩写(这是 JS 的基础)。 ES6(或 ECMAScript 2015)是最新的稳定版本,其中包含 JavaScript 以前没有的各种新功能。

服务器端代码:

Meteor.method('insertRole', function (roleName) {
  check(roleName, String);

  try {
    // Any security checks, such as logged-in user, validating roleName, etc

    MongoRoles.insert({name: roleName});
  } catch (error) {
    // error handling. just throw an error from here and handle it on client
    if (badThing) {
      throw new Meteor.Error('bad-thing', 'A bad thing happened.');
    }
  }
});

希望这会有所帮助。这完全是我的想法,根本没有测试。但它应该能让您更好地了解数据库操作的改进结构。

解决您的编辑问题

您的代码看起来不错,除了几个问题:

  • 你定义了Posts 两次,不要那样做。创建一个文件,例如/lib/collections/posts.js,并将Mongo.Collection 的声明和实例化放入其中。然后它将在客户端和服务器上执行。
  • 您的console.log 可能会返回错误或零,因为Posts.insert 在客户端是异步的。请尝试以下方法:

.

Posts.insert({title: "title-1"}, function (error, result) {
  console.log(Posts.find().count());
});

【讨论】:

  • 非常感谢您的一般提示。他们似乎对我很有帮助。也感谢 Meteor.methods 示例。但我也想以另一种方式来做。在我的问题中添加了一些代码。可以看看吗?
  • 非常感谢您的帮助!非常感谢您的努力并提示我异步点和使用回调函数的需要。大家一起为我做的。当然,如果我想看到它,我必须得到错误。
  • 试图让你的代码示例运行,但没有成功。我的计数变量永远不会改变它的值而不是 0,我不知道为什么。请再帮我一次好吗?
  • 很抱歉,您仍然遇到问题。我可以帮忙,但我需要查看所有的代码,因为可能有一些非常简单的事情会让你在某个地方绊倒。转到MeteorPad 并将您的代码复制到相应的相应窗格中(有公共/共享代码、仅限客户端、仅限服务器等)。一旦你在那里复制了你的项目,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2016-01-11
  • 2016-09-03
  • 2016-04-26
  • 2017-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
相关资源
最近更新 更多