Meteor.publish: публикация коллекции, которая зависит от другой коллекции

У меня есть функция публикации следующим образом:

Meteor.publish('tasks', function (name) {
    var project = Projects.findOne({name: name});

    return Tasks.find({projectId: project._id});
});

Предположим, что в какой-то момент в проекты были внесены изменения, в результате вышеприведенный Projects.findOne возвращает другой проект, и Tasks.find вернет другие задачи. Однако изменения, внесенные в проекты, не переиздают задачи

Я использовал replivePublish, но выясняется, что у пакета есть проблемы (а также нет модульных тестов). Итак, есть ли простой способ сделать эту функцию публикации повторно опубликованной при изменении проекта?

Ответ 1

Обзор

На момент написания статьи реактивные объединения являются нерешенной проблемой. Полный обзор см. В Реактивные соединения в Метеор.

Рекомендации

Я сильно рекомендую напрямую использовать observChanges. Это невероятно трудно понять, и легко развить утечку памяти. Если вы мне не верите, посмотрите это видео на EventedMind. Это заставит ваши глаза кровоточить.

В этой проблеме есть несколько пакетных решений. метеоритный гид рекомендует publish-composite.

Если вы считаете, что использование пакетного решения неприемлемо, внимательно ознакомьтесь с разделом "Присоединение к клиенту" от "Реактивные соединения в Метеор" . Он чист, но требует больше времени ожидания части пользователя. Также см. Мой пост в шаблон объединяется, если вы предпочитаете активировать подписки на уровне шаблона.

Ответ 2

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

Установите пакет, вызвав meteor add peerlibrary:reactive-publish.

С добавленным пакетом вы можете просто сделать:

Meteor.publish('tasks', function (name) {
    this.autorun(function (computation) {
        var project = Projects.findOne({name: name}, {fields: {_id: 1}});

        return Tasks.find({projectId: project._id});
    });
});

Точно так же, как и следовало ожидать.: -)

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