【问题标题】:In Meteor how can I publish one server side mongo collection under different names?在 Meteor 中,如何以不同的名称发布一个服务器端 mongo 集合?
【发布时间】:2012-07-29 21:48:57
【问题描述】:

我有一个名为 Profiles 的服务器端 mongo 集合。

如果用户:adminId,我需要发布和订阅整个配置文件集合。

这样管理员可以编辑、更新等...每个配置文件集合项。

但我希望用户能够看到他们的个人资料记录。

所以我尝试了这个......

客户端

MyProfile = new Meteor.Collection("myprofile");
Meteor.subscribe('profiles');
Meteor.subscribe('myprofile');

通用 - 客户端和服务器端

Profiles = new Meteor.Collection("profiles");

服务器端 - 配置文件的发布和订阅工作正常。

// this returns all profiles for this User
// if they belong to an ACL Group that has acl_group_fetch rights
Meteor.publish("profiles", function() { 
    var user_groups = Groups.find({users: this.userId()});
    var user_groups_selector = [];
    user_groups.forEach(function (group) {
       user_groups_selector.push(group._id);
    });
    return Profiles.find( {
       acl_group_fetch: {
          $in: user_groups_selector
        } 
    });
});

问题似乎从这里开始。 Profiles.find 正在返回集合项,因为我可以将它们输出到控制台服务器端。但由于某种原因,发布和订阅不起作用。客户端什么也没收到。

//  return just the users profile as myprofile
Meteor.publish("myprofile", function() {
  return  Profiles.find({user: this.userId()});
});

任何想法我做错了什么。我希望能够发布用户 A 可以插入、获取、更新、删除但用户 B(C、D 和 E)只能看到他们的记录的记录集合。

【问题讨论】:

  • Steeve - 一个小问题:小心第一次订阅('profiles');除非您将其包装在自动订阅上下文中,否则它不会在用户组更改时自动更新。我不认为这是你看到的问题。
  • 用户没有看到自己的个人资料?或者只是不是来自“个人资料”订阅的个人资料列表?您确定要等到数据加载完毕?
  • MyProfile.find 或 .findOne 在客户端的文档集合中没有任何内容。我什至已经从 Profiles 中提取了所有组代码,所以它现在发布给所有客户端只是为了看看它确实如此。这是我第一次尝试在同一个服务器端 mongo 集合上进行两次发布/订阅。
  • 如果您可以继续在 IRC 上继续讨论可能更容易?
  • 我稍后会和你联系,现在不能做 IRC。感谢您在 Google 群组中提供的帮助!

标签: meteor


【解决方案1】:

我认为您的问题更多是在 MongoDB 方面,而不是在流星方面。鉴于你的情况,我会做两个集合(组和个人资料)。

Group 集合中的每个文档都有一个数组,其中包含 DBRefs 到 Profile 集合中的文档(实际上是用户,所以我会考虑将 Profile 集合重命名为 User,因为 imo 更直观)。

Profile 集合及其文档也是如此; profile 集合中的每个文档(代表一个用户)都有一个数组字段,其中包含用户所属组的 DBrefs(Group 集合中的文档)。

【讨论】:

  • 我在 Groups 集合中遵循 [Trees] (mongodb.org/display/DOCS/Trees+in+MongoDB) 的子链接模式。每个 Group 都有一个由 [DBRefs] 组成的 users 字段,指向用户文档。我认为您建议保留组的子链接模式,然后实现一个 groups 字段,它是用户集合中的祖先数组?
  • 这行得通,但我必须维护两组记录。首先,“Group.users”字段中的“users._id”数组。其次,“users.groups”字段中的“groups._id”数组。这意味着在从组中删除或删除用户时我必须非常小心。
  • 顺便说一句,我现在正在使用这个解决方案,但它看起来不像“流星”的做事方式。 “流星”方式将是“命名”订阅客户端集合,无论原始服务器端集合如何,只要服务器端发布集合与客户端具有相同的名称。
【解决方案2】:

我不完全确定您是如何检查错误的,但我认为您可能遇到了我遇到的问题。当您使用 Profiles 集合发布数据时,即使 pub/sub 调用使用“myprofile”名称,数据始终在您为其返回游标的集合中可用......在这种情况下,您的数据在“myprofile”发布中发布将显示在客户端的“profiles”集合中。发布调用不会在客户端上创建“myprofile”集合。因此,如果您尝试在“myprofile”集合上查找(),您将看不到任何数据。 (Meteor/MongoDB 不会抱怨该集合不存在,因为它们总是会在您引用它时懒惰地创建它。)

【讨论】:

  • Iain 你是绝对正确的。我觉得从逻辑上讲,无论服务器集合如何,我都可以随意调用客户端集合。当您考虑从 X 服务器集合发布到具有不同“名称”的 N 个客户端集合时,这将是非常强大和灵活的。这将允许最终用户查看他们特定的“用户”集合,但如果最终用户是管理员,您可以发布“所有用户”。如果以这种方式工作,可能性是无穷无尽的。
  • 次要说明,正确,没有错误,但 MyProfiles 中名为“myprofiles”的集合为空,并且数据显示在 Profiles 集合中。您可以使用任何集合对此进行测试。将第一个 pub/sub 设置为 Collection 和“collection”,然后将第二个设置为 MyCollection 和“mycollection”。具有“集合”查询限制,因此它不会返回集合。完全打开“mycollection”查询并让它调用 Collection.find({}) 来获取结果集。项目将显示在 Collection 而不是 MyCollection 中的客户端上。很容易测试。
  • 这里的问题是您将集合名称与订阅名称混为一谈。如果您查看用于发布的文档(docs.meteor.com/#meteor_publish),您会看到您可以在发布方法中将数据发送到任何集合,只是如果您在发布方法中返回游标(即Collection.find),Meteor自动连接对this.set 等的调用以同步从该集合中找到的记录。
  • @Steeve:可以,但您只需要自己手动连接观察 + 设置/取消设置调用。如果您在Meteor.publish 中返回Cursor,它会为您执行此操作,并且“正常工作”(显然对集合名称的限制除外)。感兴趣的可以看这里:github.com/meteor/meteor/blob/master/packages/livedata/….
  • @TomColeman 很有趣。因此,理论上可以创建一个包,允许通过客户端上的不同“命名”Meteor.collections 发布单个集合。
【解决方案3】:

我认为这里的问题是您只需要一个集合:Profiles

所以如果你只是删除违规行

MyProfile = new Meteor.Collection("myprofile");

一切都应该正常(Profiles 集合中的两个数据集都有)。

【讨论】:

  • 是的,这在一定程度上确实有效,但它变得有点限制。管理员或有权查看所有配置文件的任何人如何知道哪一个是他们的?这就是为什么我只想将所有配置文件发布给可以对集合进行操作的人,然后将 MyProfile 发布给登录的任何人。组更复杂。所有组和用户所属的组之间存在差异。我仍然必须知道用户所在的组,即使他们可以删除所有或部分组,因为他们可能在一个组中,他们不能删除,但这会限制他们在应用程序的其他地方
  • Steeve 我原以为你会希望有一些代码可以按照myprofile = Profiles.findOne({_id: this.userId()}) 的方式来查找用户的个人资料——这样你就可以在客户端和客户端上重用该代码服务器而不是依赖于客户端上的不同行为。
猜你喜欢
  • 2012-08-28
  • 2015-04-28
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多