我想在http://crowducate.me上完成什么:
- 显示类(class)作者的用户名(即文档的“所有者”)。
当前代码:
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
如果我打开自动发布,它就会起作用。该图像显示当前状态(自动发布关闭)。如图所示,仅当当前用户与作者相同时才会呈现作者姓名。
--
一位 friend 提出了以下建议: https://gist.github.com/wiesson/1fd93d77ed9df353b7ab
"The basic idea was to attach the username to the course before providing the data with the publish method. However, as described in Meteor MongoDB find / fetch issues, the publish method should return a curser and not an array of objects.”
有什么想法可以解决这个问题吗?将所有者用户名放入数组中?如果是这样,怎么办?
P.S.:可以在此处找到源代码(目前,提交版本比部署版本多): https://github.com/Crowducate/crowducate.me
非常感谢。
最佳答案
有几种方法可以完成此连接。在我们开始之前的一些注意事项:
正如我在 this question 的回答中所解释的那样,发布功能中的排序不影响客户端上文档的顺序。
在集合名称中使用复数形式是公认的标准。当集合包含类(class)时,
类(class)
看起来很奇怪。这个问题本质上是关于连接的,所以我建议阅读 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
可能比简单的连接需要更多的计算工作。如果您在其他地方发布类(class),则在客户端上合并文档时,
所有者
很可能会被覆盖。这可以通过附加像ownerUsername
这样的字段来解决,但这也需要更昂贵的观察。如果您确实需要客户端上某处的所有者 ID,则这没有帮助。
如果用户名发生更改,它不会使用react(可能很少见,但我想我会指出这一点)。
非响应式发布 + 客户端加入
您可以像这样实现发布:
CoffeeScript
Meteor.publish 'popularCourses', ->
courseCursor = Course.find()
userIds = courseCursor.map (c) -> c.owner
userCursor = Meteor.users.find {_id: $in: userIds}, {fields: username: 1}
[courseCursor, userCursor]
JavaScript
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];
});
请注意,我很小心地只发布 userCursor
中的 username
和 _id
(您不想发布哈希值)密码和 session 数据意外)。然后您可以在客户端上连接这两个集合,如下所示:
Template.myTemplate.helpers
courses: ->
Course.find().map (c) ->
c.owner = Meteor.users.findOne(c.owner)?.username
c
优点
计算量轻且简单的发布功能。
如果用户名发生更改,则会使用react。
缺点
如果所有者发生变化,则不会使用react。
您需要在客户端上进行加入。一个有趣的替代方法是使用类似 Collection Helpers 的内容。 .
最后,我将指出您可以使用包来进行完全响应式(Reactive)连接。但是,除非所有者(或所有者的用户名)发生很大变化,否则这可能有点矫枉过正。
关于javascript - 在通过meteor的publish方法提供数据之前添加来自另一个mongodb集合的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25835854/