Как преобразовать данные, полученные через Meteor.publish?

Коллекции Meteor обладают способностью transform, которая позволяет привязывать поведение к объектам, возвращенным из монго.

Мы хотим отключить автозапуск, чтобы клиент не имел доступа к коллекциям баз данных, но мы все же хотим, чтобы функция преобразования.

Мы отправляем данные клиенту с более явным механизмом Meteor.publish/Meteor.subscribe или RPC (Meteor.call()/Meteor.methods())

Как мы можем заставить Meteor-клиента автоматически применять преобразование, как это будет при получении данных напрямую с помощью методов Meteor.Collection?

Ответ 1

(Meteor 0.7.0.1) - метеор позволяет привязывать поведение к объектам, возвращаемым через pub/sub.

Это из запроса на тягу, который я отправил в проект метеор.

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() - именно это я хочу: теперь я привязываю поведение к возвращенным данным.

Ответ 2

Пока вы не можете напрямую использовать преобразования, есть способ преобразовать результат запроса базы данных, прежде чем публиковать его. Вот что пример "опубликовать текущий размер коллекции" описывает здесь.

Мне потребовалось некоторое время, чтобы выяснить, действительно ли это простое приложение, поэтому, возможно, мой код также поможет вам:

Meteor.publish("publicationsWithHTML", function (data) {
    var self = this;
    Publications
        .find()
        .forEach(function(entry) {
            addSomeHTML(entry);  // this function changes the content of entry
            self.added("publications", entry._id, entry);
        });
    self.ready();
});

На клиенте вы подписываетесь на это:

Meteor.subscribe("publicationsWithHTML");

Но вашей модели все равно нужно создать коллекцию (с обеих сторон), которая называется "публикациями":

Publications = new Meteor.Collection('publications');

Помните, что это не очень хороший пример, так как он не поддерживает реактивность. Но сначала я нашел пример счета немного запутанным, так что, возможно, вы найдете его полезным.

Ответ 3

Try:

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();
  });
});

Ответ 4

В настоящее время вы не можете применять преобразования на сервере к опубликованным коллекциям. Подробнее см. этот. Это позволяет вам либо преобразовывать данные на клиенте, либо использовать метод метеоров. В методе вы можете заставить сервер делать все, что хотите.

В одном из моих проектов мы выполняем наш самый дорогой запрос (он объединяет несколько коллекций, денормализует документы и обрезает ненужные поля) с помощью вызова метода. Он не реагирует, но он значительно упрощает наш код, потому что все преобразования происходят на сервере.

Ответ 5

Чтобы продлить ответ @Christian Fritz, с помощью Reactive Solution, используя peerlibrary: reactive-publish

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);
    });
  });
});