javascript - 在通过meteor的publish方法提供数据之前添加来自另一个mongodb集合的信息

标签 javascript arrays mongodb meteor coffeescript

我想在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

如果我打开自动发布,它就会起作用。该图像显示当前状态(自动发布关闭)。如图所示,仅当当前用户与作者相同时才会呈现作者姓名。

enter image description here

--

一位 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/

相关文章:

c# - 如何正确地将 JSON 字符串反序列化为包含另一个类的嵌套列表的类

javascript - JQuery: trigger() 不调用相关目标

node.js - 如何使用 Nestjs 中的请求范围提供程序动态更改数据库连接?

node.js - TypeError : Cannot read property 'ref' of undefined | Express

javascript - 根据浏览器加载不同版本的jquery

javascript - AngularJS 在事件中返回一个 promise

c - 获取字符串直到第一个数字

java - 将函数中的数组与空值进行比较

java - 如何替换添加到 ArrayList 中的日期

mongodb - MongoDB 2.4 和 2.6 之间的多边形几何图形在 $not $geoWithin 中的不同语义