使用meteor将单个记录添加到mongo集合中

时间:2015-08-18 14:25:10

标签: mongodb meteor collections

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

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

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

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

在服务器上,重复的条目将输入到集合中。我不知道为什么。可能我不明白关键概念。有人能指出我吗,拜托?

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

修改-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计数'每次刷新页面。但我期望两者都一样。我做错了什么?

修改-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()
})

1 个答案:

答案 0 :(得分: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以前没有的各种新功能。
  7. 服务器端代码:

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