2014-04-25 122 views
0

首先,对一个完整的javascript noob感到抱歉,我更像是一个PHP家伙,我只是测试了流星框架。流星收集的麻烦

我通过对象的集合试图循环,并尝试通过其他收藏品作为这样添加属性:

Template.host.hosts = function() { 
    var hosts = Hosts.find(); 

    hosts.forEach(function(host) { 
     host.lastPing = Pings.findOne({id: host.id}, {sort: {timestamp : -1}}); 

     // This works fine 
     // console.log(host.lastPing.id); 
    }); 

    for (host in hosts) { 

     // This results in "TypeError: Cannot read property 'id' of undefined" 
     console.log(host.lastPing.id); 
    } 

    return hosts; 
}; 

我不明白为什么第二次的console.log不工作。

我试图寻找,但我不知道,如果问题是特定的方式来处理流星集合或我应该添加属性为JavaScript对象或成才完全无关的方式(范围等)

我简化了我的问题,试图了解发生了什么,我的真正的问题显然是一个模板循环按:

{{#each hosts}} 
    {{this.lastPing.id}} 
{{/each}} 

感谢

回答

1

三件事:

  1. MongoDB和Meteor ID存储在_id而不是id

  2. 在你forEach方法的情况下,host遍历查询集由Hosts.find()返回,但它实际上并没有给你访问文档本身。本质上,它是MongoDB中的信息的副本,而不是数据库中的文档。

    更新实际文档正确的(唯一的)方法是使用Collection.update方法:

    Hosts.update({_id: host._id}, {$set: {lastPing: Pings.findOne({id: host.id}, {sort: {timestamp : -1}}) }}); 
    

    (请注意,您只能通过_id的客户端,它是在更新为什么就是我这里所使用的,而可以在服务器上提供的任何查询。)

  3. hosts对象是光标而非阵列。这意味着当你使用for host in hosts时,你实际上遍历了游标对象的属性(它是从原型继承的),而不是一组主机,它们都没有id属性。使这项工作的一种方法是取查询集,并把它变成hosts这样的:

    var hosts = Hosts.find().fetch(); 
    

    或者,您可以用光标坚持和再次使用forEach,虽然你要么有可以快退hosts.rewind(),或重复上面的行将其重置为查询集的开头。

希望有帮助。

+0

非常感谢Hosts.update做的窍门,我将不得不再次阅读这篇详细的文章几次才能完全理解。 – Purplefish32