如何';转换';通过Meteor.publish返回的数据?

如何';转换';通过Meteor.publish返回的数据?,meteor,Meteor,Meteor Collections有一种能力,允许将行为附加到mongo返回的对象 我们希望关闭autopublish,这样客户端就不能访问数据库集合,但我们仍然需要转换功能 我们正在使用更显式的Meteor.publish/Meteor.subscribe或RPC机制(Meteor.call()/Meteor.methods())向客户端发送数据 我们如何让Meteor客户端像直接使用Meteor.Collection方法检索数据时那样自动应用转换?目前,您无法在服务器上将转换应用于已发布的

Meteor Collections有一种能力,允许将行为附加到mongo返回的对象

我们希望关闭autopublish,这样客户端就不能访问数据库集合,但我们仍然需要转换功能

我们正在使用更显式的Meteor.publish/Meteor.subscribe或RPC机制(Meteor.call()/Meteor.methods())向客户端发送数据


我们如何让Meteor客户端像直接使用Meteor.Collection方法检索数据时那样自动应用转换?

目前,您无法在服务器上将转换应用于已发布的集合。有关更多详细信息,请参阅问题。这就让您要么在客户机上转换数据,要么使用meteor方法。在方法中,您可以让服务器对数据执行任何操作


在我的一个项目中,我们通过方法调用执行最昂贵的查询(它连接多个集合,取消文档规范化,并修剪不必要的字段)。它不是被动的,但它大大简化了我们的代码,因为所有的转换都发生在服务器上。

虽然您不能直接使用转换,但有一种方法可以在发布数据库查询之前转换其结果。这就是“发布集合的当前大小”示例所描述的内容

我花了一段时间才想出一个非常简单的应用程序,所以我的代码可能也会对您有所帮助:

Meteor.publish(“publicationsWithHTML”,函数(数据){ var self=这个; 出版物 .find() .forEach(函数(条目){ addSomeHTML(entry);//此函数用于更改entry的内容 添加(“出版物”,条目._id,条目); }); self.ready(); }); 在您订阅的客户端上:

Meteor.subscribe(“publicationsWithHTML”);
但您的模型仍然需要创建一个称为“出版物”的集合(两侧):

Publications=newmeteor.Collection('Publications');
请注意,这不是一个很好的例子,因为它不能保持反应性。但一开始我发现计数示例有点混乱,因此您可能会发现它很有用。

(Meteor 0.7.0.1)-Meteor确实允许将行为附加到通过发布/订阅返回的对象

这是我提交给meteor项目的请求

Todos = new Meteor.Collection('todos', {
// transform allows behavior to be attached to the objects returned via the pub/sub communication.
      transform : function(todo) {
          todo.update = function(change) {
             Meteor.call('Todos_update', this._id, change);
          },
          todo.remove = function() {
             Meteor.call('Todos_remove', this._id);
          }
         return todo;
     }
});
todosHandle = Meteor.subscribe('todos');
通过“todos”主题返回的任何对象都将具有update()和remove()函数,这正是我想要的:我现在将行为附加到返回的数据上。

尝试:

let transformTodo = (fields) => {
  fields._pubType = 'todos';
  return fields;
};

Meteor.publish('todos', function() {
  let subHandle = Todos
    .find()
    .observeChanges({
      added: (id, fields) => {
        fields = transformTodo(fields);
        this.added('todos', id, fields);
      },
      changed: (id, fields) => {
        fields = transformTodo(fields);
        this.changed('todos', id, fields);
      },
      removed: (id) => {
        this.removed('todos', id);
      }
    });
  this.ready();
  this.onStop(() => {
    subHandle.stop();
  });
});

扩展@Christian Fritz答案,使用反应性解决方案


您不能在服务器上应用转换函数,以便在方法中进行转换吗?或者,您可以手动转换方法调用的结果。如果您的方法只是基本的数据库查询,则可能更容易显式地只允许使用和规则的某些客户端查询。这是一个很好的观点,根据需求(和复杂性)可能会很有用。我喜欢的另一个例子来自。一个重要的注意事项:集合不需要位于服务器上。self.added()应该是self.added(“publicationsWithHTML”,…)(我从问这个问题开始就知道了),当您订阅此集合时,您将无法观察到该集合的更改。例如,如果某个客户端将一个文档添加到出版物集合中,其他客户端将无法看到该新文档。“在客户端上转换”正是我们所需要的。(见我的答案)这对我有帮助。我需要单独访问游标,所以我分离了find()调用。我的结果是:let handle=cursor.observerChanges()。。。
Meteor.publish("todos", function() {
  const self = this;
  return this.autorun(function(computation) {

    // Loop over each document in collection 

     todo.find().forEach(function(entry) {

    // Add function to transform / modify each document here

      self.added("todos", entry._id, entry);
    });
  });
});