根据数据库中的信息有选择地在Meteor中发布的正确方法是什么?

时间:2014-01-28 23:23:18

标签: meteor

例如,当您的权限是基于组的,并且您的用户文档包含用户所属的组列表时。我在Items集合中发布文档,您应该只能查看groupOwner字段与您所属的组匹配的项目。

如果您可以在发布内部自动运行会很好,但我怀疑您可以:

Meteor.publish 'screened-items', ->
  Deps.autorun ->
    user = Users.findOne @userId
    return Items.find {groupOwner: {$in: user.groups}}

如果你不能,这是我能想到的最好的,但它会变得缓慢且占用大量内存。这是唯一的方法吗?

Meteor.publish 'screened-items', ->
  user = Users.findOne @userId

  # (hope that the db doesn't change between this line and the observeChanges)
  saved_items = Items.find({groupOwner: {$in: user.groups}}).fetch()
  # call @added on each item

  handle = Users.findOne(@userId).observeChanges {
    changed: (_, fields) =>
      if fields.groups
        new_items = Items.find({groupOwner: {$in: fields.groups}}).fetch()
        # compare new_items to saved_items, and call @added() or @removed() for each difference
  }

  @ready()
  @.onStop ->
    handle.stop()

2 个答案:

答案 0 :(得分:1)

您可以通过以下两种方式实现:

  1. 使用publish-with-relations包,例如:

    Meteor.publish 'screend-items', ->
      # select the current user
      Meteor.publishWithRelations
        handle: this
        collection: Meteor.users
        filter:
          _id: @userId
        options:
          fields:
            groups: 1
        mappings: [
          key: 'groupOwner'  # and map to the `groupOwner` field on Items
          collection: Items
        ]
    
  2. 对关系进行非规范化,提供用于发布的简洁用户列表

    Items._ensureIndex(userIds: 1) # best to index this field
    # basic publications
    Meteor.publish 'screend-items', ->
      # don't expose `userIds` to the client
      return Items.find({userIds: @userId}, {fields: userIds: false})
    

答案 1 :(得分:1)

如果您希望在userId更改时更改已发布的文档,则这是默认行为。

  

但是,如果登录用户更改,则会使用新值重新运行发布功能。 - 来自docs.meteor.com

Deps.autorun()仅适用于客户端,而Meteor.publish()仅适用于服务器。所以你不能在发布内部自动运行。

如果您可以让客户端看到他们所在的“群组”,则代码会更简单,因为您可以在群组更改时启动和停止订阅。像这样:

//on client 
Deps.autorun( function() {
  Meteor.subscribe( 'items', Meteor.user().groups );
});

//on server
Meteor.publish( 'items', function( groups ){
  var self = this;
  var user = Meteor.users.findOne( {_id: self.userId});

  if ( ! (user && user.groups === groups) )
    return;

  return Items.find({groupOwner: {$in: groups}});
});

否则,您需要在发布功能中使用两个观察者 - 一个用于监视用户对组的更改,另一个用于管理组中的发布项目。请参阅this example以这种方式加入集合。