我希望在http://crowducate.me上完成的任务:
当前代码:
Meteor.publish 'popularCourses', ->
# find all courses
courses = Course.find({}, {sort: {createdAt: -1}}).fetch()
for course in courses
# find each User by course owner
owner = Meteor.users.findOne({_id: course.owner})
# overwrite the ownerId with the desired username
course.owner = owner.username
return courses
如果我打开 autopublish ,它就可以了。图像显示当前状态(自动发布关闭)。如图所示,只有当前用户与作者相同时才会呈现作者姓名。
-
一位朋友建议如下: https://gist.github.com/wiesson/1fd93d77ed9df353b7ab
“基本的想法是在向数据提供发布方法之前将用户名附加到课程。但是,如Meteor MongoDB find / fetch issues中所述,发布方法应该返回一个光标而不是一个对象数组。”
任何想法如何解决?将所有者用户名放在数组中?如果是这样,怎么样?
P.S。:Sourecode可以在这里找到(目前,提交的版本比部署的版本多): https://github.com/Crowducate/crowducate.me
非常感谢。
答案 0 :(得分:3)
您可以通过多种方式完成此加入。在我们开始之前的几点说明:
正如我在this question的答案中所解释的那样,在发布功能中排序不会影响客户端上的文档顺序。
在集合名称中使用复数形式是可接受的标准。当集合包含课程时,Course
看起来很奇怪。
这个问题基本上是关于联接的,所以我建议您阅读Reactive Joins In Meteor。
您问题的字面答案是转换服务器上的文档,如下所示:
Meteor.publish 'popularCourses', ->
transform = (fields) ->
if fields.owner
username = Meteor.users.findOne(fields.owner)?.username
fields.owner = username
fields
handle = Course.find().observeChanges
added: (id, fields) =>
@added 'course', id, transform fields
changed: (id, fields) =>
@changed 'course', id, transform fields
removed: (id) =>
@removed 'course', id
@ready()
@onStop ->
handle.stop()
owner
,就好像它是用户名一样。使用observeChanges
可能比简单的连接值得更多计算工作。
如果您在其他地方发布课程,则在客户端合并文档时,owner
完全可能会被覆盖。这可以通过附加像ownerUsername
这样的字段来抵消,但这也需要更昂贵的观察。
如果您确实需要客户端上的所有者ID,这没有用。
如果用户名发生变化,则不会被动反应(可能很少见,但我认为我指出了这一点)。
您可以像这样实现发布:
Meteor.publish 'popularCourses', ->
courseCursor = Course.find()
userIds = courseCursor.map (c) -> c.owner
userCursor = Meteor.users.find {_id: $in: userIds}, {fields: username: 1}
[courseCursor, userCursor]
Meteor.publish('popularCourses', function() {
var courseCursor = Course.find();
var userIds = courseCursor.map(function(c) {return c.owner;});
var userCursor = Meteor.users.find(
{_id: {$in: userIds}},
{fields: {username: 1}
});
return [courseCursor, userCursor];
});
请注意,我要谨慎地仅发布username
_id
和userCursor
(您不希望通过以下方式发布散列密码和会话数据事故)。然后你可以在客户端加入这两个集合,如下所示:
Template.myTemplate.helpers
courses: ->
Course.find().map (c) ->
c.owner = Meteor.users.findOne(c.owner)?.username
c
计算轻量且简单的发布功能。
如果用户名更改,则为“无效”。
如果所有者更改,则不会被动。
您需要在客户端上进行加入。一个有趣的选择是使用Collection Helpers。
最后,我要指出您可以使用包进行完全反应式连接。但是,除非所有者(或所有者的用户名)发生了很大的变化,否则这可能是过度的。
答案 1 :(得分:1)
一个简单的解决方案是只发布popularCourses
和owners
,并将所有者添加到客户端上的每个课程(使用您在出版物上编写的完全相同的代码)。