首先,对不起是一个完整的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无效。
我尝试过搜索,但我不知道问题是否特定于meteor处理集合的方式,或者我应该将属性添加到javascript对象或者完全不相关的范围(范围等等)< / p>
我已经简化了我的问题,试图了解发生了什么,我的真正问题显然是在模板中循环:
{{#each hosts}}
{{this.lastPing.id}}
{{/each}}
由于
答案 0 :(得分:1)
三件事:
MongoDB和Meteor ID存储在_id
而不是id
。
在forEach
方法的上下文中,host
会遍历Hosts.find()
返回的查询集,但它实际上并不会让您自己访问这些文档。从本质上讲,它是MongoDB中信息的副本,而不是数据库中的文档。
更新实际文档的正确(且唯一)方法是使用Collection.update方法:
Hosts.update({_id: host._id}, {$set: {lastPing: Pings.findOne({id: host.id}, {sort: {timestamp : -1}}) }});
(请注意,您只能在客户端上按_id
更新,这就是我在这里使用的原因,而您可以在服务器上提供任何查询。)
hosts
对象是游标而不是数组。这意味着当您使用for host in hosts
时,您实际上是在迭代游标对象的属性(从原型继承)而不是主机数组,并且它们都没有id属性。实现此功能的一种方法是获取查询集并将其放入hosts
,如下所示:
var hosts = Hosts.find().fetch();
或者,您可以坚持使用光标并再次使用forEach
,但您必须使用hosts.rewind()
来回放它,或者重复上面的行以将其重置为查询的开头集。
希望这有帮助。